#!/usr/local/bin/perl
#################################################################################
# COPYRIGHT NOTICE																#
# Copyright (c) 1998-2007 Ira L. Gershenhorn.  All Rights Reserved.				#
#																				#
# mgFargo may be used and modified free of charge by anyone so long as			#
# this copyright notice and the comments above remain intact.  By using this	#
# code you agree to indemnify Ira L. Gershenhorn from any liability that		#  
# might arise from it's use.													#  
#																				#
# Selling the code for this program without prior written consent is			#
# expressly forbidden.  In other words, please ask first before you try and		#
# make money off of my program.													#
#																				#
# Obtain permission before redistributing this software over the Internet or	#
# in any other medium.	In all cases copyright and header must remain intact.	#
#																				# 
# mgFargo is free software; you can redistribute it and/or modify it			#
# under the terms of the GNU General Public License as published by the			#
# Free Software Foundation; either version 2 of the License, or (at				#
# your option) any later version.												#
#																				#
# mgFargo is distributed in the hope that it will be useful, but				#
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY	#
# or FITNESS FOR A PARTICULAR PURPOSE.&nbsp; See the GNU General Public			#
# License for more details.														#
#									     										#
# You should have received a copy of the GNU General Public License				#
# along with this program; if not, write to the Free Software					#
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.	#
#################################################################################
# Debug Commands
# perl mgCvt9to8.pl ??

=head1 NAME

B<mgCvt9to8.pl> - Convert a Magic 9.4 export so it looks like a Magic 8.3 export

=head1 SYNOPSIS

C<mgCvt9to8>
Copy your magic 9 export to m9a.exp and it will output to m8a.exp 
%perlpath%bin\perl  \\solo\e\dev\mgFargo\mgFargo-802.pl -i \\solo\e\dev\mgFargo\mgFargo.ini nsa

For Detailed Help type: mgCvt9to8 -h

=head1 ARGUMENTS

=head1 EXAMPLES


=head1 BUGS

=head2 Planned Enhancements

=head1 SUPPORT

Ira Gershenhorn E<lt>ira@gershenhorn.comE<gt>

=head1 HISTORY
 2006-1203 Created

=head1 AUTHOR

Ira Gershenhorn E<lt>iragershenhorn@mindspring.comE<gt>

=cut

#http://www.rexswain.com/perl5.html#string  a very nice resource
   
#no sequence numbers #0604
#use warnings;
#use strict;
use Getopt::Std;
%opt=();
getopts("vhf:i:s:",\%opt) or basicUsage();
my $debugEE = 0;
my $ppCnt = 0;
my $mgMajorVers = 0;
my $mgMinorVers = 803;
my $versionDate = "12/06/2006";
my $copyrightLine = "mgFargo V$mgMajorVers.$mgMinorVers Copyright (c) 1998-2006 Ira L. Gershenhorn & Co., Inc.";
my $generatingVB = 0;

if ($opt{h}){  detailedUsage(); }
if ($opt{m}){  manpage(); }

#the following uses are only here for Perl2exe.  It doesn't know dependencies.
if( $opt{x} ) {
	use IO;
	use IO::Seekable;
	use IO::File;
	use IO::Handle;
	use Pod::Usage;
	use Pod::Parser;
}

#if( ! -f $ARGV[0] ){ $error = "main input file \"$ARGV[0]\" does not exist"; usage();}

#Getopt::Long::Configure('bundling');
#GetOptions('verbose|v' => \$verbose,
#		  'trace' => \$trace,
#		  'help|?|h' => \$help,
#		  'manual' =>  \$manual,
#		   'debug' => \$debug,
#		   'numberfiles|n' => \$numberfiles,
#		   'programdict|p' => \$programdict,
#		   'filedict|d' => \$filedict,
#		   'uniquify|u' => \$uniquify,
#		   'start|s' => \$start,
#		   'end|e' => \$end)
#  or pod2usage(2);


   my $os = $ENV{OS};
   $context = '';
   $brktyp = '';
	$useDfNamePrefixes = 1;
	my $ddPrefixSeparator = '.';

	$flowMode{S} = 'Step';
	$flowMode{s} = '!step!';
	$flowMode{F} = 'Fast';
	$flowMode{C} = 'Combined';
	$flowMode{B} = 'on Zoom (Before)';
	$flowMode{Z} = 'on Zoom (Before)';#version 8
	$flowMode{A} = 'on Zoom (After)';
	$flowMode{J} = 'on Zoom (After)';#version 8
	$flowMode{j} = '!on zoom (after)!';#version 8
	$flowMode{Z} = '!on zoom (???)!';#version 9 line 117832
	$flowDir{F} = 'forward';
	$flowDir{C} = 'forward,back';
	$flowDir{B} = 'backwards';

	$initialTaskMode{M} ='Modify';#verified
	$initialTaskMode{C} ='Create';#verified
	$initialTaskMode{D} ='Delete'; #verified
	$initialTaskMode{E} ='Query';#verified
	$initialTaskMode{P} ='As Parent';#verified
	$initialTaskMode{L} ='Locate';
	$initialTaskMode{R} ='Range';
	$initialTaskMode{K} ='Key';
	$initialTaskMode{S} ='Sort';
	$initialTaskMode{O} ='Files'; #verified
	#$initialTaskMode{N} ='Options';#verified

	#tab string

	#$tabstr = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
	$tabstr = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; #cut in half to keep from running amok.
	$spacestr = "                                                                                                                                               ";
	my $start1 = time;
	my $start2;
	my $cnt = 0;
	my $hasApps = "N";
	my $hasModels = "N";
	my $hasTables = "N";
	my $hasPrgs = "N";
	my $hasHelps = "N";
	my $hasRights = "N";
	my $hasMenus = "N";
	my $hasComp = "N";
	my $hasAppProp = "N";
	my $hasWModels = "N";
	my $hasISN = "N";

	my $rights = 0;
	my $p = 0;#program index
	my $t = 0;#task index
	my $e = 0;#expression index
	my $lineNumber = 0;

	my $appExportFile;  #this is the import file - either application or a single export.
	$appExportFile = $opt{f};
	$supportFilesPath = $opt{s};
	if( $supportFilesPath ne ''){$supportFilesPath .= '\\';}
	$mgFargoIniPath = $opt{i};
	if( $mgFargoIniPath ne ''){$mgFargoIniPath .= '\\';}
	read_act_eng();#587
	read_fnt_eng();#600
	read_mgFargo_ini();
#
#	#override command line options with mgFargo.ini #588
#	if (defined ($ini{lc(Verbose)           })){ $opt_v = $ini{lc(Verbose)};  }
#	if (defined ($ini{lc(numberFiles)       })){ $opt_n = $ini{lc(numberFiles)};}
#	if (defined ($ini{lc(uniquifyVars)      })) { $opt_u = $ini{lc(uniquifyVars)};}
#
#	if (defined ($ini{lc(useDfNamePrefixes) })){ $opt_f = $ini{lc(useDfNamePrefixes)};}
#
#	if (defined ($ini{lc(startProgram)      })){ $opt_s = $ini{lc(startProgram)}; }
#	if (defined ($ini{lc(endProgram )       })){ $opt_e = $ini{lc(endProgram)}; }
#	if (defined ($ini{lc(progList)          })){ $opt_p = $ini{lc(progList)}; chomp($opt_p)}
#	if (defined ($ini{lc(internalFileExport)})){ $opt_d = $ini{lc(internalFileExport)}; chomp($opt_d) }
#
#	my $rowColumnFirst   = $ini{lc(rowColumnFirst     )}; #600 doesn't necessarily need to be in mgFargo.ini - will not crash if its missing.
#	my $showScaledToFit  = $ini{lc(showScaledToFit    )};
#	my $showScaledToFill = $ini{lc(showScaledToFill   )};
#	my $showAllowCrInData= $ini{lc(showAllowCrInData  )};
#
#	my $useDfNamePrefixes = defined($opt_f)?$opt_f:0;#default is not to prepend #574
#	my $uniquifyVars = defined($opt_u)?$opt_u:1; #default is to uniquify #574

#	my @dd = ();
	my $uniquifyVars = 1;#was once an option.
	
	print STDOUT "...first pass. loading variables and expressions\n";
	$pass = 1;
	open IN, "< $appExportFile ";
	load();
	close IN;

	print STDOUT "...second pass. writing doc files\n";
	$pass = 2;
	$start2 = time;
	open IN, "< $appExportFile ";
	$p = 0;
	$indentUsed = 1;
	while (readin()) {
		if ($_ eq "PRG={\n" || $_ eq "PRG_MAIN={\n"  ) {
			writeProgram();#pass=2
		}
	}
	close IN;
	print STDERR "Total Run times (secs), pass1:", $start2 - $start1 . ' pass2:', time - $start2 ;
	   

	# exit here
	sub readin{
		# not a great generator of prevline, really only used in countBrackets.
		#and the alternate assignment of prevline broke the countBrackets subroutine because prevline would always be blank.
#		if( $pass == 2 && $lineNumber > 112903 ){
#			print STDOUT "readin:$lineNumber: $_"; # current line ends in newline
#		}
		$_ = shift @saved;
		if ( !defined ($_ )) {
#			$prevline = $_;
			$_ = <IN>;
			$lineNumber ++;
		}
#		if (defined($doViewCnt)){print "readin: $_\n";}
		study;
		if (!/^TSK=/) {
			$prevline = $_;
		}
		if ($_ eq "RPR=\{"){ # in report, similar to task structure, skip it.
#			$prevline = $_;
			while (<IN>){
				$lineNumber ++;
				if (/^(PRG|PRG_MAIN)=/){
					last;
				}
	#			$prevline = $_;
			}
		}
	#	s/ISN(_2)?=\d+,?//;  # version 8 may have optional ISN numbers we don't need.
		$_;
	}
	sub expandIOmode {
		($func, $val) = @_;

		if ($val eq '')	{
			$val;
			return;
		}
	#	if ($func eq 'style') {
	#	    if ($val &   1 )  { $val = 'style1'; }
	#	    if ($val &   2 )  { $val = 'style2'; }
	#	    if ($val &   4 )  { $val = 'style4'; }
	#	    if ($val &   8 )  { $val = 'style8'; }
	#	    if ($val &  0x10 ){ $val = 'style0x10'; }
	#	    if ($val &  0x20 ){ $val = 'style0x20'; }
	#	    if ($val &  0x40 ){ $val = 'style0x40'; }
	#	    if ($val &  0x80 ){ $val = 'style0x80'; }
	#	    if ($val &  0x100){ $val = 'style0x100'; }
	#	    if ($val &  0x200){ $val = 'style0x200'; }
	#	    if ($val &  0x400){ $val = 'style0x400'; }
	#	    if ($val &  0x800){ $val = 'style0x800'; }
	#	    if ($val &  0x1000){ $val = 'style0x1000'; }
	#	    if ($val &  0x2000){ $val = 'style0x2000'; }
	#	    if ($val &  0x4000){ $val = 'style0x4000'; }
	#	    if ($val &  0x8000){ $val = 'style0x8000'; }
	#	}
	#	if ($func eq 'align') {
	#	    if ($val &   1 )  { $val = 'align1'; }
	#	    if ($val &   2 )  { $val = 'align2'; }
	#	    if ($val &   4 )  { $val = 'align4'; }
	#	    if ($val &   8 )  { $val = 'align8'; }
	#	    if ($val &  0x10 ){ $val = 'align0x10'; }
	#	    if ($val &  0x20 ){ $val = 'align0x20'; }
	#	    if ($val &  0x40 ){ $val = 'align0x40'; }
	#	    if ($val &  0x80 ){ $val = 'align0x80'; }
	#	    if ($val &  0x100){ $val = 'align0x100'; }
	#	    if ($val &  0x200){ $val = 'align0x200'; }
	#	    if ($val &  0x400){ $val = 'align0x400'; }
	#	    if ($val &  0x800){ $val = 'align0x800'; }
	#	    if ($val &  0x1000){ $val = 'align0x1000'; }
	#	    if ($val &  0x2000){ $val = 'align0x2000'; }
	#	    if ($val &  0x4000){ $val = 'align0x4000'; }
	#	    if ($val &  0x8000){ $val = 'align0x8000'; }
	#	}
		elsif ($func eq 'attr') {
			if    ($val eq 'A' ){ $val = 'Alpha'; }
			elsif ($val eq 'N' ){ $val = 'Numeric'; }
			elsif ($val eq 'B' ){ $val = 'Logical'; }
			elsif ($val eq 'D' ){ $val = 'Date'; }
			elsif ($val eq 'T' ){ $val = 'Time'; }
			elsif ($val eq 'M' ){ $val = 'Memo'; }
			elsif ($val eq 'I' ){ $attr = 'Image'; }
		}

		elsif ($func eq 'editControl') {
			if    ($val eq 'S') { $val = 'Static';     }#verified Staticincludes  Text, Lines, Ellipses, Rectangles
			elsif ($val eq 'E') { $val = 'Field';      }#verified really called Edit
			elsif ($val eq 'P') { $val = 'Pushbutton'; }#verified
			elsif ($val eq 'T') { $val = 'Table';      }#verified  #expand table info!!
			elsif ($val eq 'C') { $val = 'CheckBox';   }#verified
			elsif ($val eq 'L') { $val = 'Slider';     }#verified
			elsif ($val eq 'O') { $val = 'OLE2'; }
			elsif ($val eq 'I') { $val = 'Image'; }
			elsif ($val eq 'H') { $val = 'RichEdit';   }#Ferenc Polgar
			elsif ($val eq 'M') { $val = 'HTMLFile';   }#Ferenc Polgar
			elsif ($val eq 'N') { $val = 'Line';   }#Ferenc Polgar
			elsif ($val eq 'X') { $val = 'ActiveX';   }#Ferenc Polgar
			elsif ($val eq 'R') { $val = 'Radio';      }#verified
		}
		elsif ($func eq 'mod') {#Access (6)
			if    ($val eq 'R') { $val = 'Read'; }
			elsif ($val eq 'W') { $val = 'Write'; }
			elsif ($val eq 'A') { $val = 'Append'; }
			elsif ($val eq 'D') { $val = 'Direct'; }
		}
		elsif ($func eq 'read') {#Open Mode (8)
			if    ($val eq 'N') { $val = 'Normal'; }
			elsif ($val eq 'F') { $val = 'Fast'; }
			elsif ($val eq 'D') { $val = 'Damaged'; }
			elsif ($val eq 'R') { $val = 'Reindex'; }
		}
		elsif ($func eq 'opn') {#Share mode (5)
			if    ($val eq 'R') { $val = 'Read'; }
			elsif ($val eq 'W') { $val = 'Write'; }
			elsif ($val eq 'N') { $val = 'None'; }
		}
		elsif ($func eq 'endcheck') {
			if    ($val eq 'A') { $val = 'After'; }
			elsif ($val eq 'B') { $val = 'Before'; }
			elsif ($val eq 'I') { $val = 'Immediate'; }
		}
		elsif ($func eq 'ioformat') {
			if    ($val eq 'P') { $val = 'Page'; }
			elsif ($val eq 'L') { $val = 'Line'; }
			elsif ($val eq 'N') { $val = 'None'; }
		}
		elsif ($func eq 'iomedia') {
			if    ($val eq 'P') { $val = 'Printer'; }
			elsif ($val eq 'C') { $val = 'Console'; }
			elsif ($val eq 'S') { $val = 'Standard File'; }
			elsif ($val eq 'I') { $val = 'Internal File'; }
			elsif ($val eq 'U') { $val = 'User Driver'; }
		}
		elsif ($func eq 'eventscope') {
			if    ($val eq 'S') { $val = 'Subtree'; }
			elsif ($val eq 'T') { $val = 'Task'; }
		}
		elsif ($func eq 'eventcall') {
			if    ($val eq 'P') { $val = 'Program'; }
			elsif ($val eq 'T') { $val = 'Task'; }
		}
		$val;
	}

   sub load{
	   $| = 1;  #flush STDOUT.  otherwise no output for a long time.
	   $_ = <IN>;
	   if (/^VRSN=(\d+)/) { $magicVersion = $1; }
		   else{
			   die "no VSRN?\n";
	   }
	   if ( $magicVersion != "940" ){
		   die "wrong VSRN, expecting 940, got $magicVersion\n";
	   }

	   loadHeader();
	   if ($hasModels=="Y"){loadModels() ;	  }
	   loadFiles();
#	   loadMainProg();
	   loadProgs();
	   if ($hasMenus=="Y"){ loadMenus() ;	}
	   loadAppProps();
	   $lineNumber = 0;
   }
   sub loadHeader{
	   print STDOUT "Loading Header...\n";
	   do {
		   readin(); #$_ = <IN>;
		   #print STDOUT $_; print $cnt; print " ";
		   chomp;
		   if (/^APPLICATION=(\d+)/) { $hasApps = $1; }
		   if (/^MODEL=(\d+)/) { $hasModels = $1; }
		   if (/^TABLE=(\d+)/) { $hasTables = $1; }
		   if (/^PROGRAM=(\d+)/) { $hasPrgs = $1; }
		   if (/^HELP=(\d+)/) { $hasHelps = $1; }
		   if (/^RIGHT=(\d+)/) { $hasRights = $1; }
		   if (/^MENU=(\d+)/) { $hasMenus = $1; }
		   if (/^COMPONENT=(\d+)/) { $hasComp = $1; }
		   if (/^APP_PROP=(\d+)/) { $hasAppProp = $1; }
		   if (/^WITH_MODELS=(\d+)/) { $hasWModels = $1; }
		   if (/^ISN=(\d+)/) { $hasISN = $1; }
	   } until ($cnt++ > 100 || /^MODELS=/);
	   if(	$hasApps != "Y" ||
			$hasPrgs != "Y" ||
			$hasTables != "Y"
		 ){
		   die "The export isn't an exported application or it doesn't have Programs or Tables\n";
	   }
   }
	#Load Models until FILE= is encountered
   sub loadModels{
	   print STDOUT "Loading Models...\n";
	   do {
		   #skip the Models.  We don't use them. Just want names.
		   #Just like we ignore Types in Version 8.
		   parseModelsline();
		   readin(); #$_ = <IN>;
	   } until ($cnt++ > 100000 || /^FILE=/);
	   #print $cnt; print " "; print STDOUT $_;
	   print "\n";
   }
   sub loadFiles{
	   print STDOUT "Loading Files...\n";
	   initDataDictionary();
	   do {
		   parseFile();
		   readin(); #$_ = <IN>;
	   } until ($cnt++ > 500000 || /^PRG_MAIN=/);
	   #print $cnt; print " "; print STDOUT $_;
	   print "\n";
#	   exit(); #end after loading files.
   }
   sub loadMainProg{
	   print STDOUT "Loading Main Program...\n";
	   do {
		   readin(); #$_ = <IN>;
	   } until ($cnt++ > 900000 || /^PRG=/);
	   print $cnt;
	   #print " "; print STDOUT $_;
	   print "\n";
   }
   sub loadProgs{
	   print STDOUT "Loading Programs...\n";
	   do {
		   parseProg();
		   readin(); #$_ = <IN>;
	   } until ($cnt++ > 2000000 || /^MENU=/);#for test I was using 19000, now 2M. Latest 9.4 file is 1.5M
	   print $cnt; print " ";
	   #print STDOUT $_;
	   print "\n";
   }
   sub loadMenus{
	   print STDOUT "Loading Menus...\n";
	   do {
		   readin(); #$_ = <IN>;
	   } until ($cnt++ > 99000 || /^CTL=/);
	   #print $cnt; print " "; print STDOUT $_;
	   print "\n";
   }
   sub loadAppProps{
	   print STDOUT "Loading Application Properties...\n";
	   do {
		   readin(); #$_ = <IN>;
	   } until ($cnt++ > 101000 || eof);
	   print STDOUT "Found EOF, exiting\n";
	   #print $cnt; print " "; print STDOUT $_;
	   print "\n";
   }

   sub loadRights{
	   print STDOUT "Loading Rights...\n";
	   do { #probably not correct
		   if (/^RGHT=\{NAME="(.*?)",KEY="(.*?)",PBLC=(.)/) {
			   $rights++;
			   $rights[$rights]->{name} = $1;
			   $rights[$rights]->{key}  = $2;
			   $rights[$rights]->{public}= $3;
		   }
		   readin(); #$_ = <IN>;
	   } until ($cnt++ > 101000 || eof);
	   print STDOUT "Found EOF, exiting\n";
	   #print $cnt; print " "; print STDOUT $_;
	   print "\n";
   }

   sub initDataDictionary{
		$ddfile = 0;
		$dd[0]{desc}= 'None';
		$dd[0]{key}->[0]= 'None';
	}
	sub ddFile{
		$fileFolder = $dbname = $desc = $name = '';
		$fileFolder = $1 if /FOLDER=\"(.*?)\"/;
		$desc = $1 if /DESC=\"(.*?)\"/;
		$name = $1 if /NAME=\"(.*?)\"/;#eg DEBUG.DAT for the DBG file
		$dbname = $1 if /DBNAME=\"(.*?)\"/;
		($comment) = $_ =~  /COMMENT="([^"]+)"/;#I don't do anything with this.
		$ddfile++;
		$ddfield = 0;
		$ddkey = 0;
		$dd[$ddfile]{folder}= $fileFolder;
		$dd[$ddfile]{name}= $name;
		$dd[$ddfile]{dbname}= $dbname;
		$dd[$ddfile]{desc}= $desc;
		$dd[$ddfile]{key}->[0]= 'None';
		print STDOUT "\n\tFILE: $ddfile: $desc FOLDER:$fileFolder ";  #DISPLAY FILE on STD OUTPUT
	}
	sub ddField{
		my $desc = shift;
		# if it has an ISN, override the ddfield index.
		($comment) = $_ =~  /COMMENT="([^"]+)"/;#I don't do anything with this.
		my $fieldIdx = 0;
		if(/,ISN=(\d+),/){
			$fieldIdx = $1;
		}
		else {
			$ddfield++;
			$fieldIdx = $ddfield;
		}
		$dd[$ddfile]{fields}->[$fieldIdx]= $desc;
#		print STDOUT " $desc , ";
	}
	sub ddKey {
		$desc = $1 if /DESC=\"(.*?)\"/;
		$ddkey++;
		$dd[$ddfile]{key}->[$ddkey]= $1;
		($comment) = $_ =~  /COMMENT="([^"]+)"/;#I don't do anything with this.
#		print STDOUT " KEY: $desc ";
	}
	sub parseModelsline{
		if ( /^MODELS=\{DESC="(.+)"/){
			$modeln++;
			($comment) = $_ =~  /COMMENT="([^"]+)"/;#I don't do anything with this.
			$comment =~ s//\n/g;#replace backspaces with new lines
			$models[$modeln]->{desc}=$1;
		}
		elsif ( /^PROP={ID="MODEL/) {
			$models[$modeln]->{attr}= ucfirst(lc($1)) if /OBJ="FIELD_(.+)"/;#Capitalization or Initial Caps
		}
		elsif ( /^PROP={ID="PICTURE/) {
			$models[$modeln]->{pic}= $1 if /VAL="(.+)"/;
		}
		elsif ( /^PROP={ID="RANGE/) {
			$models[$modeln]->{range}= $1 if /VAL="(.+)"/;
		}
		#should dump them to separate file with usage count. :-)
		# and list of unused models.
	}
	sub parseFile{
		if ( /^FIELD=/) { $prevSeg = 'FLD' }
		if ( /^FILE=\{(FOLDER|DBNAME|DESC|NAME)/){	ddFile(); }
		elsif ( /^FIELD=\{DESC=\"(.*?)\",/) {ddField($1); }
		elsif ( /^KEY=/){	ddKey();}
	   #don't care about PROPLIST, PROP, SEG elements.
	}
   # get description of event from an index. desciption may be in a higher task or main prog
	sub evtDesc {
		my $evt_id = shift;
		my $desc = '?evt-'.$evt_id.'?';
	 #  		   $evt[$p]->{$hier}->{$eventn}->{parent} = $event_forceExit;
		$desc;  # return
	}

	sub varDesc {
		my $varFound =0;
		my $varletter_id = shift;
		my $h = $hier;
		my $startdesc = $desc = '?var-'.$h.'-'.$varletter_id.'?';
#		if($h>0){$h--;}

		if( $ppCnt > 0 ){
			print STDOUT "varDesc:$desc\n"; ##START HERE
		}
		while (1) {  #loop through levels looking for match - from bottom to top; Must look at prg=1 in version 9.
			if (defined($var[$p]->{$h}->{$varletter_id}->{desc})) {
				$desc = $var[$p]->{$h}->{$varletter_id}->{desc};
				$varFound=1;
				if($debugEE){print STDOUT "varDesc-p.h.v.desc,start:$p,$h,$varletter_id,$desc,$startdesc\n"; }
				last;
			}
			elsif ($h eq '1' ) { #if no match at top level ; should kick out here if no match in this program.
				last;
			}
			elsif ($h eq '2' || $h eq '3'|| $h eq '4' ) { #if no match at top level ; should kick out here if no match in this program.
				#if we get here, we mistook a child task as a task at the same level.
				print STDOUT "Serious problem: Bad Level interpretation: varDesc:$lineNumber: $desc $startdesc\n"; ##START HERE
				exit();
				last;
			}
			else {
				$h =~ s/(\.\d+)$//;   #remove one level; if the top is not=1, could be stuck here forever.
			}
			if( $ppCnt > 0 ){
				print STDOUT "h:$h line:$_\n"; ##START HERE
				exit();
			}
		}
		if( !$varFound && $p != 1 ){# look in Main Program at the globals.
			$h = $hier;
			while (1) {  #loop through levels looking for match - from bottom to top
				if (defined($var[1]->{$h}->{$varletter_id}->{desc})) {
					$desc = $var[1]->{$h}->{$varletter_id}->{desc};
					$varFound=1;
					last;
				}
				elsif ($h eq '1' ) { #if no match at top level
					last;
				}
				else {
					$h =~ s/(\.\d+)$//;   #remove one level
				}
			}
		}
		$desc;
	}
	#THe function IN is a problem.  Most functions have more than two chars.  This one doesn't and I don't want to treat as a var.
	#eg.  EXP="CndRange (NOT (IN (IF,'','  1','  2','  3')),IF)",
	# must look ahead for paren.  Should be same issue as IF detection.
	sub expandedExpression{
		my $in = shift;
		my $lastToken = 'none';
		my $result = '';

		if( $ppCnt > 0 ){
			print STDOUT "expandedExp:$cnt:$lineNumber: $in\n";
		}

		while ($in =~ m{
				 (
				 \'\'           | # null string
				 \'[^\']*?\'    | # strings
				 IN\s\( |	#IN detection should be same as IF detection
				 IF\s\( |
				 \sOR\s |
				 \sAND\s |
				  <> |
				  <= |
				  >= |
				 [&<>\.\-+*,=\(\)\/] | # punctuation
				 [A-Za-z]+         | # symbols
				 [0-9.]+          #572 attempt to fix problem of spaced out decimal in 0.02 construct
				 )
			   }xg){
			$token = $1;
			if ( $token =~/IF\s\(/){
				$lastToken = 'if';					$result .= $token . ' ';
			}
			elsif ( $token =~/IN\s\(/){
				$lastToken = 'in';					$result .= $token . ' ';
			}
			elsif ( $token =~/\s(OR|AND)\s/){
				$lastToken = 'and-or';			    $result .= $token;
			}
			elsif ( $token =~/\'[^\']*?\'/){
				$lastToken = 'string';				$result .= $token;
			}
			elsif ($token =~ /[&<>+*,=\'\(\)\/]/){
				if (($lastToken eq 'string') && ($token eq '&')) {
					$result .= ' ';
				}
				$lastToken = 'punct';
				if( $token eq '=' ){
					$result .= '==' . ' '; #573 use equivalence. There are never assignments within expressions.
				}
				else {
					$result .= $token . ' ';
				}
			}
			else{
				if ($lastToken eq 'string'){
					$lastToken = 'const';		$result .= $token;
				}
				else{
					if ( $token =~ /^[A-Z]{1,2}$/){
						$lastToken = 'var';		$result .= varDesc($token) . ' ';
						if($debugEE){print STDOUT " [EE:$token,$lastToken,$result] ";}
					}
					else{
						$lastToken = 'keyword';	$result .= $token . ' ';
					}
				}
			}
		}
		$result =~ s/\'([A-Z]+)\'VAR/'@' . varDesc($1)/ge; 	#0586 replace any instances of "'xx'VAR" with "@variable".
		$result;
	}
	sub countBrackets{ #counts excess brackets on a line.
		my $count;
		my $rights = 0;
		my $lefts = 0;

		$prevline =~ s/".*?"//g;  #strip out strings so we don't get fooled by brackets inside the strings.
		while ($prevline =~ m/(\}+),/g){
			$rights += length $1;
		}
		while ($prevline =~ m/=(\{)/g){
			$lefts += length $1;
		}
		$count = $rights - $lefts;
	}
	sub	setHierarchicalPosition{
	# This is called when we start a new task.  We need to figure out if the new task is a lateral move or another level down.
	#
	# EXP: no brackets => subtask,
	#	1 => close current task and next task is on the same level.
	#	2+ => level after ascending n-1 levels.
	# TXT, ACTV, BLOCK: a surfeit of 1 bracket will close the preceding DSP. That's expected.  Any more close previous tasks.
	# OLECLASS: surfeit of 1 bracket: closes prior DIT_INFO, 2: closes prior ITM, 3: closes prior DSP
	# PIC (version 5): surfeit of 1 closes prior ITM, 2: closes prior DSP.
	# EVENT_TRIGGER:
	#  surfeit of 1 => child.  (the surfeit of 1 is closing the prior EVNT element).
	#  surfeit of 2 => same level.
	# EVENT_TRIGGER closing an EVNT must subtract 1 to get actual bracket count.
	# EVENT_TRIGGER closing an ITM/PROPLIST must subtract 4 to get actual bracket count.
	
	# PROP with DATA=  2 brackets closes out prev DSP, TSK is 1 down in hierarchy, 3 close current hierarchy, so task is over one.
	# PROP with no DATA= 2 brackets closes out prev DSP, TSK is 1 down in hierarchy, 3 close current hierarchy, so task is over one.
	#
	#0609 HTML Merge
	# What I currently print:
	#	Form: 13 Individual File Heading Class 4 Type:HTMLMerge, Detail, IsChild:N, Color:6, Font:1,Default Table Edit Field~MS Sans Serif~8~0, UOM_FACTOR={X=1,Y=1},
	#	BLOCK={DX=100,DY=10},TMPL_FILE="%template%ruleSmInd.htm",TAG_PRFX="<!$",TAG_SUFX=">",
	#	+-Row-Col-Rows-Cols-Allow------- Name -------------------Attr-Pic---------------------------+
	#
	# Whats in the app export
	#	DSP={
	#	DSP_INFO={NAME="Individual File Heading",CLSS=4,MOD=N,COLOR=6,STYLE=2048,FONT=1,ISCHLD=N,GRIDX=10,GRIDY=10},
	#	UOM_FACTOR={X=1,Y=1},
	#	
	#	FRM={},
	#	BLOCK={DX=100,DY=10},TMPL_FILE="%template%ruleSmInd.htm",TAG_PRFX="<!$",TAG_SUFX=">",
	#	MERGE_PARM={EXP=1,
	#	PIC="300",TXT="GeneratorProgPath"},
	#	MERGE_PARM={EXP=2,
	#	PIC="30",TXT="GenDateTime"},
	#	MERGE_PARM={EXP=3,
	#	PIC="30",TXT="LastModifiedDate"},
	#	MERGE_PARM={FLD="O",
	#	PIC="60",TXT="ProcessDesc"},
	#	MERGE_PARM={FLD="N",
	#	PIC="50",TXT="XPath"},
	#	MERGE_PARM={FLD="P",
	#	PIC="2000",TXT="LongDesc"}},
	#
#       print STDOUT "countBrackets, prev: $prevline\n";
		$bktCount = countBrackets();
		if ($prevline =~ /^EVENT_TRIGGER/){
			if( $trigContext eq 'EVNT' ){	$bktCount -= 1; }
			elsif( $trigContext eq 'ITM' ){	$bktCount -= 5; }
			else {	$bktCount -= 1; }#from ITM
			print STDOUT "  --setHierarchicalPosition: EVENT_TRIGGER: $lineNumber $bktCount, $trigContext, $prevline\n";
			$trigContext = '';
			$trigContext = 'EVNT';#so I don't have to look for the EVNTs
		}
		$bktCount -= 1 if ($prevline =~ /^(ACTV|TXT|BLOCK)/);
		$bktCount -= 2 if ($prevline =~ /^(PIC)/);
		$bktCount -= 3 if ($prevline =~ /^(OLECLASS)/);
		if ($prevline =~ /^(FLD_RNG)/){#should work like expression.  what to do with this info??
			$bktCount -= 0;
#			print STDOUT "  --setHierarchicalPosition: FLD_RNG: $lineNumber $bktCount, $prevline\n";
		}
		if ($prevline =~ /^PROP=/){
			if ($propListType eq 'DSP'){ $bktCount -= 2;}
			else {$bktCount -= 3; }
#			print STDOUT "  --setHierarchicalPosition: PROP, DATA: $lineNumber $bktCount, $prevline\n";
		}
#		print STDOUT "Hierarchy:  $bktCount, $prevline\n";
#		print STDOUT "this line:  $_\n";
		if ( $bktCount == 0) { #add a level
			$hier .= '.1';
		}
		elsif ($bktCount >= 1 && $hier eq '1') {
			print STDOUT "ERROR: gotcha bracket Count=$bktCount, there's a new element that ends a task to deal with on bracket count!\n";
			print STDOUT "Line Number:  $lineNumber\n";
			print STDOUT "Previous line: $prevline\n";
			print STDOUT "This line:  $_\n";
		}
		elsif ($bktCount == 1) { #move over at same level.
			$hier_before = $hier;
			$hier =~ s/(\d+)$/$1+1/e;   #move laterally, increment the last number
#			print STDOUT "  --setHierarchicalPosition: Lateral ==1: $lineNumber $hier $hier_before $bktCount $propListType  <$prevline>\n";
		}
		else { #move up then over  never expect negative..  Possible large positive to close many levels
			$hier_before = $hier;
			$hier = getTaskHier( $bktCount-1 );
			$hier =~ s/(\d+)$/$1+1/e;
#			print STDOUT "  --setHierarchicalPosition: Lateral Else: $lineNumber $hier $hier_before $bktCount $propListType  <$prevline>\n";
		}
	}
	sub initTaskVarsPrescan{#for prescan
		$formNumber=0;
		$vr=0;  #virtual-real index
		$e=1;
		$j=1;
		$v=0;#these are pre-inited. They really do begin at 1. see ^FIELD
		$maindbf=0;
	}
	sub setPropListType{
		if ( $prevSeg eq 'DSP' ){ $propListType = 'DSP'; }
		elsif ( $prevSeg eq 'ITM' ){ $propListType = 'ITM'; }
		elsif ( $prevSeg eq 'FLD' ){ $propListType = 'FLD'; }
		else  {
			$propListType = 'OTH';
#			print STDOUT "  --parseprog: PROPLIST: $lineNumber $propListType prevSeg:[$prevSeg] \n\tTHIS:$_";
#			exit();
		}
		$prevSeg = '';
	}
   sub doEvents_EventTrigger{
	   readin();#EVNT is always followed by EVENT_TRIGGER
       if( /^EVENT_TRIGGER=/){
		   $trigContext = 'EVNT';
	       ($parent) = $_ =~ /PARENT=(\d+),/;
	       ($actv) = $_ =~ /ACTV=(\d+),/;
	       $evt[$p]->{$hier}->{$eventn}->{parent} = $event_forceExit;
	       $evt[$p]->{$hier}->{$eventn}->{actv} = $event_forceExit;
	       $evt[$p]->{$hier}->{$eventn}->{actvs} = $event_forceExit;
	       #$actvs = $action_from_code{$actv} if $actv ne '';
	       if ($parent ne ''){#parents here should never exist. as these events are the parents.
		       ($actv) = $_ =~ /OBJ=(\d+),/;#this is in PRG_MAIN
		       $actvs =  $actv;#for now
	       }
		   $trigger = '';
	       ($trigtype) = $_ =~ /TRIG_TYPE=(.),/;
	       if($trigtype eq 'S'){$tts='System';}
	       elsif($trigtype eq 'I'){$tts='Internal';}
	       elsif($trigtype eq 'U'){$tts='User';}
	       elsif($trigtype eq 'N'){$tts='None';}
	       else{$tts='?Other?';}
		   $evt[$p]->{$hier}->{$eventn}->{trigger}=$trigger;
		   
	       $evt[$p]->{$hier}->{$eventn}->{trigtype} = $trigtype;
	       $evt[$p]->{$hier}->{$eventn}->{tts} = $tts;
       }
       else{
		   print STDOUT "ERROR: EVNT not followed by EVENT_TRIGGER\n";
	       #unshift @saved, $_; # push that on the stack, it was not expected.
       }
   }
   # While Parsing the Programs, pick up the control items for use in control references.
   sub parseProg{  #from loadProgs. A first pass function #pass=1
##		if( $p > 24 && $lineNumber > 125354 && $ppCnt < 5 ){
##			print STDOUT "parseprog:$ppCnt:$cnt:$lineNumber: $_\n";
##			$ppCnt++;
##		}
	   
	   if (/^EXP="(.*)"[,\}]/){   #EXP followed by comma or brace
			if( $ppCnt > 0 ){
				print STDOUT "parseprog:$ppCnt:$cnt:$lineNumber: $_\n";
			}
			#if($e eq '3' ){$debugEE = 1;}
		   $tempexpr = expandedExpression($1);
			$debugEE = 0;
			#if($e eq '3' ){print STDOUT "EXP: $e, $1, $tempexpr\n";}
		   $tempexpr =~ s/""/"/g;  # substitute single quotes for doubled quotes.
		   $exp[$p][$t][$e] = $tempexpr;
		   $e++;
	   }
	   #start here <<<<<<<  removing the x makes it hang.  the unshift??
	   # This EVNT is the last thing in a task, its after the EXP section. so it must be picked up on Pass 1.
	   elsif (/^EVNT=/){  #events resemble vars in that they are referenced in the same way, have the same scope
		   $eventn++;
		   $event_forceExit = '';
		   $event_desc = '';
		   ($event_forceExit) = $_ =~ /FORCE_EXIT=(.)/;
		   ($event_desc) = $_ =~ /DESC="([^"]+)"/;
		   $event_desc =~ s/""/"/g;  # substitute single quotes for doubled quotes.

		   ($comment) = $_ =~  /COMMENT="([^"]+)"/;#I don't do anything with this.
		   $comment =~ s//\n/g;#replace backspaces with new lines

		   #if( $p eq '2'){#468 USA Letters
			#   print STDOUT "pass 1 USA Letter Brk/RaiseEvnt: $event_desc//$hier//$eventn//$_";#debug
		   #}
		   $evt[$p]->{$hier}->{$eventn}->{desc} = $event_desc; #this value is read in readEventTrigger 
		   $evt[$p]->{$hier}->{$eventn}->{forceexit} = $event_forceExit;
		   
		   doEvents_EventTrigger();
		   #print STDOUT "hier = $hier\n";
	   }
	   elsif (/^TSK=/){
		   $t++;
		   $eventn = 0;# just added this in 940-10
		   initTaskVarsPrescan();
		   setHierarchicalPosition();
		   #print STDOUT "hier = $hier\n";
	   }
	   elsif (/^(PRG|PRG_MAIN)=/){
		   initTaskVarsPrescan();
		   $p++;
		   $t=1;
		   $hier='1';
		   $eventn = 0;
		   # print STDOUT "\n\t $p\n";
		   # print when HDR is received.  more info then
		}
		elsif (/^HDR=/ ){  #v055
			$desc = '--';#v055
			$desc = $1 if (/\{DESC="(.+?)",/);#v055
			print STDOUT "\n\t$p.$desc" if ($hier eq '1');
			if (!$opt_p || $hier ne '1') {
				$prgtaskName[$p]->{$hier}->{desc} = $1;
				$prgtaskName[$p]->{$hier}->{idx} = $t;
			}
		}
		elsif (/^SLCT={NAME="([][A-Z\^]+)",/){ #0602  enable characters after Z, right square bracket must be first character in character class.
			parseSelect();
		}
		elsif (/^LNK=\{DB=\{OBJ=(\d+)/){
			$dbf = $1;
		}
		elsif (/^END_LINK/){
			$dbf = $maindbf;
			$lnkref = '';
		}
		elsif (/^DB/) {
			$maindbf = $1 if $_ =~ /DB=\{OBJ=(\d+)/;
			$dbf = $maindbf;
		}
		elsif (/^RMRK=/){  #if the remark field contains  "LNKREF=blah", 
			# then a real field may be rendered "filename.blah_fieldname"
			if ( /LNKREF=(\w+)/) {
				$lnkref = '_' . $1;
			}
		}
		elsif (/^ITM=/){  #
			$prevSeg = 'ITM';
			$thisItm = 0;
			$thisItm = $1 if ( $_ =~ /TEST_ID=(\d+)/);
			if( $formType == "GUI0"){
				$nextItm++;
				#print STDOUT "\nITM: $p, $hier, $nextItm\n";
			}
		}
		elsif (/^DSP=/) {#NAME does not directly follow the brace
			$prevSeg = 'DSP';
			$formNumber++;	#reset with each task
			$ctrlnum = 0;
			$nextItm = 0;  #doesn't hurt to reset here too.
			$lastTestId = '';
			$lastTestId = $1 if ($_ =~ /LAST_TEST_ID=(\d+)/);
		}
		elsif (/^FIELD=\{DESC=\"(.*?)\",/) {
			$prevSeg = 'FLD';
			$v++;
			$virt[$p][$t][$v]->{desc}= $1;
			($comment) = $_ =~  /COMMENT="([^"]+)"/;
			$virt[$p][$t][$v]->{comment}= $comment;
		}
#		elsif (/^PROPLIST=\{MODEL=\"(.+)_(.+)\"/) { #expect FIELD, FORM, CTRL _ GUI0,  _ ACTIVEX, STATIC, LINE, RICH_EDIT, PUSH_BUTTON, CHECKBOX,
		elsif (/^PROPLIST=\{MODEL=\"(.+)\"/) { #expect FIELD, FORM, CTRL
			doPropList();
			if( $propList=="CTRL" ){
				$ctrlnum++;
			}
		}
		elsif (/^PROP=\{ID=\"NAME\",DATA=\{VAL="(.*?)"/){
			#print STDOUT "PROP ID NAME DATA VAL: $p, $hier, $1, $propList, $propType, $propObject, $ctrlnum, $nextItm\n";
			if( $propList eq "FORM" ){
				$prgtaskName[$p]->{$hier}->{form}->[$formNumber]->{desc} = $1;  #assign the name of the form.
				$formType = $propType;
				if( $formType eq "GUI0" ){ #lets start counting ITMs.
					$nextItm = 0;
				}
			}
			elsif( $propList eq "CTRL" ){#not all have names, but some do.
				$prgtaskName[$p]->{$hier}->{form}->[$formNumber]->{$ctrlnum}->{desc} = $1;  #assign the name of the control.
				$prgtaskName[$p]->{$hier}->{form}->[$formNumber]->{$ctrlnum}->{item} = $thisItm;  #assign the name of the control.
				$prgtaskName[$p]->{$hier}->{form}->[$formNumber]->{$ctrlnum}->{itemType} = $itemType;  #assign the name of the control.
				#print STDOUT "CTL PROP NAME: $formType, $hier, $1, $thisItm, $itemType\n";
				if( $formType eq "GUI0"){# is numbering here same as at ITM level?? we'll find out.
					#print STDOUT "PUTITM: $nextItm, $hier\n";
					$prgtaskName[$p]->{$hier}->{GUI0}->{$nextItm}->{desc} = $1;
				}
			}
		}
		elsif (/^PROP=\{ID=\"PICTURE\"/) {
			if( $propList eq "FIELD" ){
				$virt[$p][$t][$v]->{pic} = $1 if $_ =~ /VAL="(.+?)"/;
			}
		}
		elsif (/^PROP=\{ID=\"MODEL\"/) {
			if( $propList eq "FIELD" ){
				$modeln = 0;
				$virt[$p][$t][$v]->{model} = $modeln = $1 if $_ =~ /\{OBJ=(\d+)/;
				#put in the model info, but they might be overriden
				if( $modeln ){
					$virt[$p][$t][$v]->{model_desc} = $models[$modeln]->{desc};
					$virt[$p][$t][$v]->{attr}  = $models[$modeln]->{attr};
					$virt[$p][$t][$v]->{pic}  = $models[$modeln]->{pic};
					$virt[$p][$t][$v]->{range}  = $models[$modeln]->{range};
				}
				$virt[$p][$t][$v]->{attr} = ucfirst(lc($1)) if $_ =~ /OBJ="FIELD_(.+)"/;
			}
		}
		elsif ( /^PROP={ID="RANGE/) {
			if( $propList eq "FIELD" ){
				$virt[$p][$t][$v]->{range} =  $1 if /VAL="(.+)"/;
			}
		}
		elsif ( /^PROP={ID="TRIGGER/) {
			$trigContext = 'ITM';
		}
# not sure if we need these field properties.  Type is descriptive, range? attr nice to have. not exactly the same
#			$virt[$p][$t][$v]->{type}  = $1 if $_ =~ /TYP=([0-9]+),/;
#			$virt[$p][$t][$v]->{range} = $1 if $_ =~ /RNG="(.+?)",/;
#			$attr = $1 if $_ =~ /ATTR=(.)/;
#			$virt[$p][$t][$v]->{attr} = expandIOmode( 'attr', $attr);
		
#		else {
#			print STDOUT $_; print "\n";
#		}
   }
   sub parseSelect{
	   #SLCT stays roughly the same 8-9.  A few fields added.
	   #However, in 9, the lettering begins after fields selected in the Main Program.  They don't begin from 'A' in every program.
	   #At one site, Main Program (PRG_MAIN) goes to CD.   However, what it means is that loops must include prg=1.
	   #intialization is not an issue, because Select statements always give the appropriate letter. 
		$varletter = $1;
		my $desc;

		if (/FLD=(\d+),MOD=V,/){
			$desc = $virt[$p][$t][$1]->{desc};
			$var[$p]->{$hier}->{$varletter}->{type} = 'Virt';
			$var[$p]->{$hier}->{$varletter}->{'ref'} = \$virt[$p][$t][$1];
		}
		elsif (/FLD=(\d+),MOD=R,/){
			if (defined($dd[$dbf]{fields}->[$1])){
				my $ddPrefix = '';
				if ( $useDfNamePrefixes ){
					$ddPrefix = $dd[$dbf]{desc} . $ddPrefixSeparator
				}
				$desc = $ddPrefix . $dd[$dbf]{fields}->[$1];
				$var[$p]->{$hier}->{$varletter}->{type} = 'Real';
			}
			else{
				$desc = '?undefined-'.$dbf.'-'.$1;
			}
		}
		if (/IS_PRM=(\d+)/){
			$virt[$p][$t][$1]->{prm}=$1;#is a Parameter, Y or N.
		}

		my $varSuffix = '';
		if ($lnkref ne '') {
			$lnkref = $lnkref;
		}
		if ($uniquifyVars){
			my $i=0;
			while ($var[$p]->{vars}->{$desc . $lnkref . $varSuffix}){
				$i++;
				$varSuffix = '_' . $i;
			}
		}
		$desc .= $lnkref . $varSuffix;
		#if($varletter eq 'CM'){print STDOUT "SLCT PUT-p-h-v-d-dbf:$p,$hier,$varletter,$desc,$dbf";}
		$var[$p]->{$hier}->{$varletter}->{desc} = $desc;
		$var[$p]->{vars}->{$desc } = 1;
		$vr++;
		$var[$p]->{$hier}->{$vr} = $desc;
	}



	sub nextVar
	{
		$currentVar++;
		my $highChar = $currentVar/26;
		my $lowChar = $currentVar % 26;

		my $highCharA = ($highChar==0)?'':chr($highChar+65);
		my $lowCharA = chr($lowChar+65);
		$currentVarA = $highCharA . $lowCharA;
	}
	sub tabOut{
		#why distinguish $indentUsed from $indentLevel?
#		print substr $tabstr, 0, $indentUsed;
		print substr $tabstr, 0, $indentLevel;
	}
	sub getWrtRead{
		my $dir = shift;

		($mode, $io, $dsp) = $_ =~ /MOD=(.),IO=\{(.+?)\},DSP=\{(.+?)\}/;
		$ioTsk = 0;
		$dspTsk = 0;
		$ioIdx = 0;
		$dspIdx = 0;
		$ioTsk  = $1 if $io  =~ /TSK=(\d+)/;
		$ioIdx  = $1 if $io  =~ /IDX=(\d+)/;
		$dspTsk = $1 if $dsp =~ /TSK=(\d+)/;
		$dspIdx = $1 if $dsp =~ /IDX=(\d+)/;

		$ioHier = getTaskHier( $ioTsk );
		$dspHier = getTaskHier( $dspTsk );

		$dsp = $prgtaskName[$p]->{$dspHier}->{form}->[$dspIdx]->{desc};

		$io = $prgtaskName[$p]->{$ioHier}->{form}->[$ioIdx];
		$format = expandIOmode('ioformat', $prgtaskName[$p]->{$ioHier}->{io}->[$ioIdx]->{'format'});
		$media =  expandIOmode('iomedia',  $prgtaskName[$p]->{$ioHier}->{io}->[$ioIdx]->{media});
		$access = expandIOmode('mod',      $prgtaskName[$p]->{$ioHier}->{io}->[$ioIdx]->{access});

		print "$dir Form: $dsp ON \"$prgtaskName[$p]->{$ioHier}->{io}->[$ioIdx]->{desc}\" $media  $access  $format  File: $prgtaskName[$p]->{$ioHier}->{io}->[$ioIdx]->{file}";

	}
	sub getTaskHier {
		my $levels = shift;
		my $x = $hier;

		while ($levels > 0) {
				$x =~ s/(\.\d+)$//;   #remove one level
				$levels--;
			}
		$x;
	}
	#hopefully this is not the FLW in the task descriptor eg. FLW=B,DEL=N,END=N,EMOD=ABI,   online/batch,  never,always(Y), expr ends, ends after, before,immediate. (end=Y, = yes it ends)
	#no this is the standard FLW={CND=Y,MOD=B,DIR=C}} on the end of most expressions.
	# while MOD and DIR is irrelevant in all but MAIN, CND is always relevent.
	sub doViewFlw{
		#What is a MOD=s,j, R?
		$isBlock    = $_ =~ /^BLOCK=\{END/;#600
		($blockMode) = $1 if ($_ =~ /MOD=(.)/);#now Mod=I,E,L If,Else,Loop; was only MOD=V in version 8
		#$isBlockElseMode    = $_ =~ /MOD=E/;#new in 9
		$isSelect   = $_ =~ /^SLCT=/;
		( $flwCond, $flowMode, $flowDir ) = $_ =~ /CND=(Y|N|\d+),MOD=(.),DIR=(.)/;

		if ($enableFlowStr) {
			if (/^UPD=/){
				$defFlowSpeed = $ini{lc(defFlowSpeedUpdate)};
				$defFlowDirection = $ini{lc(defFlowDirectionUpdate)};
			}
			else{
				$defFlowSpeed = $ini{lc(defFlowSpeed)};
				$defFlowDirection = $ini{lc(defFlowDirection)};
			}
			if ( $taskFlow eq 'Online' ){
				if    ($flowMode eq $defFlowSpeed){ $flowstr = ''; }
				elsif ( $flowMode !~ /S|F|C|B|A|Z|J|j|s/) {$flowStr  = "unknown mode ?$flowMode?";     }
				else {					  	    $flowStr  = "\t// " . $flowMode{$flowMode};	}

				if    ($flowDir eq $defFlowDirection){ $flowstr .= ''; }
				elsif ( $flowDir  !~ /F|C|B/  )   {$flowStr .= ' unknown dir';  		        }
				else { 				 		    $flowStr .= "\t// "     . $flowDir{$flowDir};	}

			}
		}
		if ( $flwCond eq 'Y' ){
			$indentExp = 'Y';
			if ($isBlock){
				if($blockMode eq 'I'){#If
					$indentLevel++;
					print "Do\n"; #never see this
					tabOut();
				}
				elsif($blockMode eq 'E'){#Else
					#$indentLevel--;
					print "Else";# a new line here just gets a blank line.
					#tabOut();
					#$indentLevel++;
				}
				# probably impossible.  A loop without condition is like a loop forever.
				elsif($blockMode eq 'L'){#loop mode, like if with condition
					$indentLevel--;
					print "Loop\n";#never see this.
					tabOut();
					$indentLevel++;
				}
				else {
					print "?Block Mode?\n";
				}
			}
			elsif ($indentExp ne 'Y' ) {
				$indentLevel--;
				$indentExp = 'Y';
			}
		}
		else{
			if ($flwCond ne 'N') {
				if (defined(   $exp[$p][$t][$flwCond])){
					$flwCond = $exp[$p][$t][$flwCond];
				}
				else{
					$flwCond = '?undefined?';
				}
			}
			$indentLevel++;
			$indentUsed = $indentLevel;
			if ( $indentExp ne $flwCond ){# a new condition
				$indentExp = $flwCond;
				if ( $flwCond eq 'N' ){
					if ($isSelect){
						#should know if its a batch task or online.
						if( !($taskFlow eq 'Batch' && $isRecordMain )){#don't do this for Batch Record Main.
							print "Never do/Land on fields:\n";
							tabOut();
						}
					}
					else {
						print "Never do:\n";
						tabOut();
					}
				}
				else{
					if($blockMode eq 'L'){print "Loop while ($flwCond)";}
					else {print "If $flwCond";}
					print "\n" if !$isBlock;
					tabOut();
				}
			}
			else{ #not a new condition
				print "\t" if !$isSelect;#just added the if to prevent undo nesting of Reals:
			}
			$indentLevel-- if ! $isBlock;
		}
	}
	sub readEventTrigger {
		my($callerSeg) = $_[0];
		if( /^EVENT_TRIGGER=/){
			$trigContext = 'EVNT';

			$eventString = "";
			$parent = "";
			($trigtype) = $_ =~ /TRIG_TYPE=(.),/;
			if($trigtype eq 'S'){# system events are keys.
				$tts='System';
				($eventKey) = $_ =~ /KEY=(\d+)/;
				$eventString = "Key:$eventKey," . $key_from_code{$eventKey};
			}
			elsif($trigtype eq 'I'){
				$tts='Internal';
				($i) = $_ =~ /ACTV=(\d+),/;
				$eventString = $action_from_code{$i} if $i ne '';
			}
			elsif($trigtype eq 'R'){ 
				$tts='Error';
				($errType) = $_ =~ /ERR_TRIG=(.)/;
				#onscreen these show 1-9
				if($errType eq ''){$eventString = 'Any';}
				elsif($errType eq '1'){$eventString = 'Locked Row';}
				elsif($errType eq '2'){$eventString = 'Duplicate Index';}
				elsif($errType eq '3'){$eventString = 'Constraint Failure';}
				elsif($errType eq '4'){$eventString = 'Trigger Failure';}
				elsif($errType eq '5'){$eventString = 'Record has been updated';}
				elsif($errType eq '6'){$eventString = 'Record Changed by another user';}
				elsif($errType eq '7'){$eventString = 'Insert/Update/Delete failure';}
				elsif($errType eq '8'){$eventString = 'Unmapped Errors';}
				else {$eventString = "$errType";}
			}
			elsif($trigtype eq 'U'){  #this is true at least for both RAISE_EVNT and BRK
				$tts='User';
				($i) = $_ =~ /OBJ=(\d+),/;#this is in PRG_MAIN if parent is non-blank
				($parent) = $1 if ($_ =~ /PARENT=(\d+),/);
				if( $parent ne '' )
						{ $eventString = $evt[1]->{1}->{$i}->{desc};}
				else	{ $eventString = $evt[$p]->{$hier}->{$i}->{desc};}
				#if( $p eq '2'){#468 USA Letters
				#	print STDOUT "USA Letter Brk/RaiseEvnt: $i//$hier//$parent//$eventString// $_";#debug
				#}
			}
			else{$tts='?Other?';}
			if( $callerSeg eq "RAISE_EVENT" ){
				print "Raise Event: $tts:$eventString";
			}
		}
		else{
			print STDOUT "ERROR: $callerSeg not followed by EVENT_TRIGGER\n";
			#unshift @saved, $_; # push that on the stack, it was not expected.
		}
	}
	sub printCallComRemoteItems{
		$cc_remote = $cc_wait = $cc_sync = $cc_reason = $cc_callcnv = '';

		$cc_remote = $1 if( /REMOTE_PROGRAM="(.+)",W/);# If I don't put the W, it picks up too much. Need to know how to limit.
		$cc_wait =  $1 if( /WAIT=(.)/);
		$cc_sync =  $1 if( /SYNC_UPDATE=(.)/);
		$cc_reason =  varDesc($1) if( /REMOTE_REASON_CODE="(.+)"/);
		$cc_callcnv =  $1 if( /CALL_CNV=(.)/);

		if( $cc_callcnv eq 'M'){ $option = 'Call Method';}
		elsif ( $cc_callcnv eq 'S'){ $option = 'Set Property';}
		else { $option = $cc_callcnv;}
		print " $cc_reason.$cc_remote, Option:$option, WAIT:$cc_wait, SYNC:$cc_sync";
	}
	# example 1 - 4 args.  'arg' #1 is really a return value placeholder
	#CALL_TSK={MOD=C,TSK={},LOCK=N,
	#ARG={SKIP=Y,NAME="Return Value",TYPE=24,VTSTYLE=8},
	#ARG={EXP=26,SKIP=Y,NAME="ConnectionString",TYPE=8,VTSTYLE=10},
	#ARG={SKIP=Y,NAME="UserID",TYPE=8,VTSTYLE=10},
	#ARG={SKIP=Y,NAME="Password",TYPE=8,VTSTYLE=10},
	#ARG={SKIP=Y,NAME="Options",TYPE=3,VTSTYLE=10},REMOTE_PROGRAM="Open",WAIT=Y,SYNC_UPDATE=N,REMOTE_REASON_CODE="BV",CALL_CNV=M,FLW={CND=Y,MOD=s,DIR=C}},
	# example 2 - return value is actually used.
	#CALL_TSK={MOD=C,TSK={},LOCK=N,
	#ARG={VAR="BV",SKIP=N,NAME="Value",TYPE=12,VTSTYLE=8},REMOTE_PROGRAM="ActiveConnection",WAIT=Y,SYNC_UPDATE=N,REMOTE_REASON_CODE="BW",CALL_CNV=S,FLW={CND=Y,MOD=s,DIR=C}},
	# example 3 - no args. return value not used.  
	#CALL_TSK={MOD=C,TSK={},LOCK=Y,
	#ARG={SKIP=Y,NAME="Return Value",TYPE=24,VTSTYLE=8},REMOTE_PROGRAM="Save",WAIT=Y,SYNC_UPDATE=N,REMOTE_REASON_CODE="CJ",CALL_CNV=M,FLW={CND=Y,MOD=S,DIR=C}},

	#CALL_TSK={MOD=T,TSK={OBJ=1},LOCK=Y,
	#ARG={EXP=2,SKIP=N},
	#ARG={EXP=3,SKIP=N},WAIT=Y,SYNC_UPDATE=N,FLW={CND=Y,MOD=s,DIR=C}},
	sub pass2_CALL_TSK{
		$callTaskIndentExpr = $indentExp; #need this for Args.
		$argN = 0;
		($mode) = $_ =~ /MOD=(.),/;
		($task) = $_ =~ /TSK=\{OBJ=(\d+)\}/;#always blank for call com.
		($lock) = $_ =~ /LOCK=(.)/;
		($dsp) = $_ =~ /DSP=(\d+),/;#always blank for call com.
		if( $mode eq 'P' ){
			$calltarget = $prgtaskName[$task]->{'1'}->{desc};
			$calltarget = '?unknown calltarget?' if $calltarget eq '';
			print "Call Prog: $calltarget";
		}
		elsif( $mode eq 'T'){
			$calltarget = $prgtaskName[$p]->{$hier . '.' . $task }->{desc};
			$calltarget = '?unknown calltarget?' if $calltarget eq '';
			print "Call Task: $calltarget";
		}
		elsif( $mode eq 'E'){
			$calltarget = $exp[$p][$t][$task];
			$calltarget = '?unknown calltarget?' if $calltarget eq '';
			print "Call Exp: $calltarget";
		}
		elsif( $mode eq 'U'){
			$calltarget = $exp[$p][$t][$task];
			$calltarget = '?unknown calltarget?' if $calltarget eq '';
			print "Call UDP: $calltarget";
		}
		elsif( $mode eq 'C'){
			print "Call COM: ";
			printCallComRemoteItems();
		}
		elsif( $mode eq 'R'){
			print "Call Remote: ";
			printCallComRemoteItems();
		}
		else {
			print "Call $mode: ?unknown mode?";
		}
	}
	sub pass2_lnk{#only called from doView
		$db = 0;
		$key = 0;
		$dir = '';
		$cls = 0;
		$views = 0;
		$view = 0;
		$mod = 0;
		$rtrn ='';

		$db    = $1 if /DB=\{OBJ=(\d+)/;
		$key   = $1 if /KEY=(\d+)/;
		$dir   = $1 if /DIR=(.)/;
		$cls   = $1 if /CLS=(\d+)/;
		$views = $1 if /VIEWS=(\d+)/;
		$view  = $1 if /VIEW=(\d+)/;
		$mod   = $1 if /MOD=(.)/;
		$rtrn  = $1 if /RTRN="(.+)"/;


		print "Link ";
		if    ($mod eq 'R'){ print "Query   ";  }
		elsif ($mod eq 'W'){ print "Write   ";  }
		elsif ($mod eq 'N'){ print "Validate";  }
		elsif ($mod eq 'A'){ print "Create  ";  }
		print " : $db $dd[$db]{desc}  Key: $key $dd[$db]->{key}->[$key]  Dir: $dir";
		my $var = varDesc $rtrn;

		print "   Returning: $var"  if $rtrn ne '';
		$rtrn = ''; #615 clear in a few extra places to make sure its not reused.
		$indentLevel++;
	}
	sub	pass2_LCT{ #only called from doView
		$min ='';
		$max ='';
		$min = $1 if $_ =~ /MIN=(\d+)/;
		$max = $1 if $_ =~ /MAX=(\d+)/;
		if ($min eq $max ){
			print "\tLocate == $exp[$p][$t][$min]"; #\n"; #573 changed to == equivalence
			# add a new line at end if you want more spacing.
			tabOut();
		}
		else {
			if ($min ne '')	{ 
				print "\tLocate\tFrom: $exp[$p][$t][$min]";
				if ($max ne ''){
					print "\n";
					tabOut();
				}
			}
			print "\tLocate\tTo: $exp[$p][$t][$max]" if $max ne '';
		}
	}
	sub pass2_RNG{  #only called from doView
		$min ='';
		$max ='';
		$min = $1 if $_ =~ /MIN=(\d+)/;
		$max = $1 if $_ =~ /MAX=(\d+)/;
		if ($min eq $max ){
			print "\tRange == $exp[$p][$t][$min]";#\n";
			# add a new line at end if you want more spacing.
			tabOut();
		}
		elsif(1){
			#57  add code to put from and to on same line, also do for locate.
			if ($min ne '' || $max ne '')	{
				if ($min ne '' || $max ne '')	{
					print "\tRange";
				}
			}
			if ($min ne '' )	{
				print "\tFrom: $exp[$p][$t][$min] ";
			}
			if ($max ne ''){
				print "\tTo: $exp[$p][$t][$max]"
			}
			#print "\n";
			# add a new line at end if you want more spacing.
			tabOut();
		}
		elsif(0){
			#57  old code getting replaced
			if ($min ne '')	{
				print "\tRange From: $exp[$p][$t][$min]";
				if ($max ne ''){
					print "\n";
					tabOut();
				}
			}
			if ($max ne ''){
				print "\tRange   To: $exp[$p][$t][$max]"
			}
		}
	}
	#sub pass2_EXT{ #only called from doView
	#			$exp='';
	#			$clr='';
	#			$wait='';
	#			($exp) = $1 if $_ =~ /EXP=(\d+)/;
	#			print "Exit to: $exp[$p][$t][$exp]";
	#			if ( $_ =~ /CLR=(.)/){
	#				if ($1 == 'Y') {
	#					print " and clear the screen";
	#				}
	#				else {
	#					print " and do not clear the screen";
	#				}
	#			}
	#			if ( $_ =~ /WAIT=(.)/) {
	#				if (!defined ($ini{lc(defExitToWait)}) ) {
	#					$ini{lc(defExitToWait)} = '';
	#				}
	#				if ($1 == 'Y') {
	#					print " and wait for completion" if $ini{lc(defExitToWait)} != 'Y';
	#				}
	#				else {
	#					print " and do not wait for completion" if $ini{lc(defExitToWait)} != 'N';
	#				}
	#			}
	#}
	sub pass2_rearrange_SLCT{
		#in the most extreme case (both LCT and RNG), the before and after would be:
		# before:  SLCT...; LCT..; RNG..FLW
		# after:   SLCT..FLW; LCT..; RNG..
		# because we want the Flow (condition) to be with the select.
		$orig = $_;
		undef @lsaved; #lsaved is only used here, saved is used in readin.
		for ($i=1; $i<=2; $i++){ #will fetch up to two more lines looking for LCT + RNG
								# second seems to have extra indent.
			readin();
			#print STDOUT "SLCT with no FLW: $_";#debug
			if (/^(LCT|RNG)/){
				push @lsaved, $_;
				chomp($orig);
				$orig = $orig . 'HAS_'.$1.'=Y,';# adds a HAS_RNG=Y, or HAS_LCT=Y, 
				if (/FLW=\{/){ #concat this line to original if it has a FLW info. meaning its the last LCT,RNG
					$_ = $orig . $_;
					last;
				}
			}
			else{ #didn't find a LCT or RNG -> time to leave loop.
				push @lsaved, $_;
				$_ = $orig;
				last; #don't process further, do the readin for next.
			}
		}
		unshift @saved, @lsaved; #add whole lsaved array to beginnnig of saved.eg if saved was ('C','D) and lsaved was ('A','B'), then after saved would be ('A','B','C','D)
		undef @lsaved;
	}
	#Raise event with NO args, Flow and Condtion is on the Event_Trigger and it ends in two brackets and comma			
	#RAISE_EVENT={
	#EVENT_TRIGGER={TRIG_TYPE=U,COMP_EVNT_ISN={PUB_OBJ={OBJ=4,COMP_OBJ=-1}}},RSEVNT_IMMIDIATE=89,FLW={CND=Y,MOD=S,DIR=C}},

	#Raise event with 2 args, Flow is on last arg and Event_Trigger does not end with brackets,comma.			
	#RAISE_EVENT={
	#EVENT_TRIGGER={TRIG_TYPE=U,COMP_EVNT_ISN={PUB_OBJ={OBJ=2,COMP_OBJ=-1}}},RSEVNT_IMMIDIATE=89,
	#ARG={EXP=197,SKIP=N},
	#ARG={EXP=236,SKIP=N},FLW={CND=485,MOD=S,DIR=C}},
	sub pass2_RAISE_EVENT{
		readin();
		readEventTrigger( 'RAISE_EVENT' );
	}
	sub doView{ #from a ^BRK=
		$doViewCnt = 0;
		($comment) = $_ =~  /COMMENT="([^"]+)"/;
		if($comment ne ''){
			$comment =~ s//\n/g;#replace backspaces with new lines
			print "	------------Comments-----------\n";
			print $comment;
			print "	-------------------------------\n";
		}
#		print "doView: $_\n";
		while (readin()){
			$doViewCnt++;
			if (/^(BRK|DSP)/){ #leave doView when we get one of these - means brk is done.
				if(/^DSP/){ $prevSeg = 'DSP';}
				unshift @saved, $_;
				last;
			}
#			$indentUsed = $indentLevel if ! /^RMRK/;
			$indentUsed = $indentLevel;
			# MUST PUT EVERY ELEMENT WE ENCOUNTER IN THIS LIST, otherwise it will exit
			if ( /^(SLCT|LCT|RNG|RMRK|STP|LNK|END_LINK|CALL_TSK|EXE|UPD|WRT|READ|SCN|EXT|EVENT_TRIGGER|RAISE_EVENT|ARG)/){
				tabOut();  #need tabout for every expression that prints text.
			}
			elsif (/^BLOCK/){
				if(/,MOD=(I|L),/){tabOut();}
				elsif(/,MOD=E,/){$indentLevel--; tabOut(); $indentLevel++;}
			}
			elsif (/^(END_BLK|HDLR_FLOW)/){			}# no tabout required because nothing printed.
			else{
				#print STDOUT "quit doView: $_";#debug
				unshift @saved, $_;
				last;
			}
			if( ! /FLW=\{/  ){#if flow not part of these functions, must move it up.
				if (/^(CALL_TSK|RAISE_EVENT)/ ) {  # flow not part of call, then are args
					pass2_rearrange_argfcn();
				}
				if (/^SLCT/) {  # flow not part of select, means a Locate or Range follows which does hold the FLW info
					pass2_rearrange_SLCT();
				}
			}
			#if( TRUE || ($context eq 'Task' && $brktyps eq 'Prefix' )){
			#	print STDOUT "$context, $brktyps, $_";#debug
			#}
			$flowStr = '';
			#if ( $enableFlowStr && /FLW=\{/){
			if ( /FLW=\{/  && !/^(ARG|LCT|RNG)/){	# handles the flow (at least the condition in FLW )
				doViewFlw();
			}
			if(/^RAISE_EVENT=/){
				pass2_RAISE_EVENT();
			}
			# would be nice to be able to delay this output til after we determine that there is or is not
			# a locate or range expression, in order to keep the locate and range on the same line as the assign.
			# Does it matter.  kind of nice to have on other lines. or I can add a field to indicate there are following lines.
			elsif (/^SLCT=\{NAME="([A-Z]{1,2})"/){
				print "$var[$p]->{$hier}->{$1}->{type}:$var[$p]->{$hier}->{$1}->{desc}";
				if (/ASS=(\d+)/){ print "\t=\t$exp[$p][$t][$1]"; }
				#Add code to check if line ends with '},' because if so, nl is ok, but if not, let the locate/range add the newline.
				$locate_range_lines = 0;
				if(/HAS_RNG=/){$locate_range_lines++;}
				if(/HAS_LCT=/){$locate_range_lines++;}
				if( $locate_range_lines > 0 ){
					readin();
					if (/^LCT=/){ pass2_LCT();}
					elsif (/^RNG=/){ pass2_RNG();}
				}
				if( $locate_range_lines > 1 ){
					readin();
					if (/^LCT=/){ pass2_LCT();}
					elsif (/^RNG=/){ pass2_RNG();}
				}
			}
			elsif (/^RMRK="(.*?)",/){
				if ( $1 eq '')	{ print "//-------------------------------------------------------------------------"; }
				else			{ print "// $1"; }
			}
			elsif (/^CALL_TSK=/){ pass2_CALL_TSK();}
			elsif (/^ARG=/){
				$argN++;
				if( $callTaskIndentExpr ne 'Y' && $callTaskIndentExpr ne ''){
					print "\t";
				}
				print "\t$argN|";
				if( /ARG=\{VAR="(\w+)"/  ){
					print varDesc($1);
				}
				elsif ( /^ARG=\{EXP=(\d+)/  ){
					my $tmp = $exp[$p][$t][$1];
					if ($tmp =~ /\'([A-Z]+)\'VAR/) {
						$tmp = '@' . varDesc($1);
					}
					print $tmp;
				}
				elsif (	/ARG=\{SKIP=Y/  ){
					print "!Parameter Skipped!";
				}
				print " as " . $1 if(/NAME="([^"]+)"/);#don't want a quote in match string
				if(/VTSTYLE=(\d+)/){
					if( $1 eq '8'){print " as OUTPUT ";}
					elsif( $1 eq '10'){print " as INPUT ";}
					else {print " as VTStyle=" . $1; }
				}
				print " as Type=" . $1 if(/TYPE=(\d+)/);
			}
			elsif (/^STP=/){
				print "Put Warning " if $_ =~ /MOD=(V|W)/;
				print "Put Error   " if $_ =~ /MOD=E/;

				print $1 if $_ =~ /TXT="(.*?)",/;
				print $exp[$p][$t][$1] if $_ =~ /EXP=(\d+)/;
			}
			elsif (/^LNK=/){ pass2_lnk(); }
			elsif (/^END_LINK,/){ $indentLevel--; $lnkref = '';}
			elsif (/^BLOCK=\{END/){			}
			elsif (/^END_BLK/){ $indentLevel--; }
			elsif (/^EXE=\{EXP=(\d+)/){
				$exp =  $1;
				print "Evaluate: $exp[$p][$t][$1]";
				$rtrn  = $1 if /,FLD="(.+)"/;
				my $var = varDesc $rtrn;

				print "   Returning: $var"  if $rtrn ne '';
				$rtrn = ''; #615 clear in a few extra places to make sure its not reused.
			}
			elsif (/^UPD=/){ #should be getting here in TP of #2
				$updateLine = '';
				($fld, $exp, $mode, $abort ) = $_ =~ /FLD="(.+)",EXP=(\d+),MOD=(.),ABRT=(.)/;
				$inc = ( $mode eq 'I' )?'+':'';
				$updateLine = varDesc($fld) . "\t$inc=\t$exp[$p][$t][$exp]";
				print OUT "$updateLine";
				if ( $complete) {
					print OUT "\t//$mode,$abort";
				}
				#if( TRUE || ($context eq 'Task' && $brktyps eq 'Prefix' )){
				#	print STDOUT "$context, $brktyps:  $updateLine";
				#	#print STDOUT "UPD: $fld ". varDesc($fld)." $context, $brktyps, $_";#debug
				#}
			}
			elsif (/^WRT=/){
				getWrtRead( 'Output' );
			}
			elsif (/^READ=/){
				getWrtRead( 'Input' );
			}
			elsif (/^SCN=/){
				$exp = 0;
				$dsp = 0;
				$mod = '';
				$edit = '';
				$exp = $1 if /EXP=(\d+)/;
				$dsp = $1 if /DSP=(\d+)/;
				$mod = $1 if /MOD=(.)/;
				$edit = $1 if /EDIT=(.)/;
				$edit = $edit eq 'S'?'Scan':'Edit';
				print "Browse $edit $exp[$p][$t][$exp]";
			}
			elsif (/^EXT=/){
				($exp) = $_ =~ /EXP=(\d+),/;
				$wait = '';
				$show = '';
				$rtrn = '';
				$clr  = '';

				print "Exit to: $exp[$p][$t][$exp]";
				$wait  = $1 if /,WAIT=(.)/;
				$show  = $1 if /,SHOW=(.)/;
				$rtrn  = $1 if /,RTRN="(.+)"/;
				my $var = varDesc $rtrn;

				print "  Returning: $var"  if $rtrn ne '';
				print "  Wait  " if $wait = 'Y' && $wait ne $ini{lc(defExeWait)} ;
				print "  Hide  " if $show eq 1  && $show ne $ini{lc(defExeShow)} ;
				print "  Normal" if $show eq 2  && $show ne $ini{lc(defExeShow)} ;
				print " Clearscn" if $clr eq 'Y'  && $clr ne $ini{lc(defExeShow)} ;
				$rtrn = ''; #615 clear in a few extra places to make sure its not reused.
			}
	#		elsif (/^EXT=/){
			#	pass2_EXT();
	#		}
			elsif (/^LCT=/){ #fix this to resemble range which looks correct
				pass2_LCT();
			}
			elsif (/^RNG=/){
				pass2_RNG();
			}
			elsif (/^EVENT_TRIGGER=/){
			   $trigContext = 'EVNT';
#				print "doView:$_\n";
			}
			elsif (/^NDLR_FLOW=/){
#				print "doView:$_\n";
			}
#			print "doViewEnd:$_\n";
			print "$flowStr\n" if (!/^END_(BLK|LINK)/ );
		}#end While
#		print "doViewCnt: $doViewCnt\n";
		undef ($doViewCnt);
	}
	#endof doView?

	# this is Group Prefix Break.
    #BRK={LEVEL=G,TYP=P,DIT_CTRL=-1,DSP=-1,REFERENCE="CV",POS=3,LENGTH=11,SCOPE=S,PROP=78,ENGINE_DIR=S,SHOW_MSG=89,ENABLED=89,
    #EVENT_TRIGGER={TRIG_TYPE=S,COMP_EVNT_ISN={PUB_OBJ={COMP_OBJ=-1}}},

	# on a User Handler, the user action is in EVENT_TRIGGER....PUB_OBJ={OBJ=(\d+)  , for RAISE_EVENT, its enough to use OBJ=(\d+)
	
	sub	doBreak{
		$context = 'Record';
		while (readin()){
			$indentLevel = 1;
			$indentUsed = $indentLevel;
			$indentExp = 'Y';
			if (/^(DSP|DRPD)/) { # there was an '=' sign on the end . Worked in Unix, Not in NT
				if(/^DSP/){ $prevSeg = 'DSP';}
				unshift @saved, $_ ;
				last;
			}
			elsif (/^BRK/) {
				my $ctlString ='';
				my $ctl = '';
				my $brkRef = $brkRefDesc = '';
				my $trigtype;
				my $actv;
				my $actvs;
				#print STDOUT "dobreak: $indentLevel, $_";
				$_ =~ /DIT_CTRL=(.)(\d*),/;
				if( $1 ne '-' ){
					# in v9, when DIT_CTRL is something other than -1, then its a Level=C Typ=V,C or P. or an H/U and with/without a reference.
					# if a ctrl is 24 then its the 24th ITM, print the NAME VAL. In v9 i see them as high as 49.
					# in the DSP whose PROPLIST MODEL is FORM_GUI0  (zero).
					#$ctlString = "Ctrl: $1$2"; #link to ITM={TESTID=X,  PROP={ID="NAME" VAL
					# these items must be scanned in advance.
					$combo = "$1$2"*1;
					
					#print STDOUT "combo: $combo, $hier, $p\n";
					$ctlString = $prgtaskName[$p]->{$hier}->{GUI0}->{$combo}->{desc};
				}
				if( $_ =~ /REFERENCE="([A-Z]+)"/){#var - don't know what its for- don't print
					$brkRef= $1;
					$brkRefDesc= varDesc($brkRef);
				}
				$context= $1 if $_ =~ /LEVEL=(.)/;#R=Record, T=Task, H=Handler  Record Main--> $context =R, $brktyp=M
				$brktyp= $1 if $_ =~ /TYP=(.)/;#S=Suffix,P=Prefix,M=Main, U=User
				if($context eq 'R' ){ $context = 'Record';}
				elsif($context eq 'T' ){ $context = 'Task';}
				elsif($context eq 'H' ){ $context = 'Handler';}
				elsif($context eq 'C' ){ $context = 'Control';}
                elsif($context eq 'G' ){ $context = 'Group';}
				 $brktyps = '?unknown?';
				if($brktyp eq 'S' ){ $brktyps = 'Suffix';}
				elsif($brktyp eq 'P' ){ $brktyps = 'Prefix';}
				elsif($brktyp eq 'M' ){ $brktyps = 'Main';}
				elsif($brktyp eq 'U' ){ $brktyps = 'User';}
				elsif($brktyp eq 'C' ){ $brktyps = 'Change';}# only for Control
				elsif($brktyp eq 'V' ){ $brktyps = 'Verification';}# only for Control

				$isRecordMain = $context eq 'Record' && $brktyp eq 'M';
				#only has meaning in certain context.  In others it is still set, but not referenced.
				$reference = '';
				if (/FLD="([A-Z]+)"/) { $reference = $1;}
				if (/REFERENCE="([A-Z]+)"/) { $reference = $1;} #more likely than FLD in 9.x
				#if (/FLD="([A-Z]+)"/) {
				#	$context = 'On Change of ' . $var[$p]->{$hier}->{$1}->{desc} ;
				#}
				#if (/REFERENCE="([A-Z]+)"/) { #more likely than FLD in 9.x
				#	$context = 'On Change of ' . $var[$p]->{$hier}->{$1}->{desc} ;
				#}
				readin(); #$_ = <IN>;
				readEventTrigger( 'BRK' );

				if ($context eq 'Handler'){
					print "\nOperations: $context $brktyps $tts $eventString  $ctlString"; #I removed newline, put back if run together occurs
					$enableFlowStr = 0;
					doView();
				}
				elsif ($context eq 'Control'){
					print "\nOperations: On Change of ". $var[$p]->{$hier}->{$1}->{desc} . " $brktyps $tts $eventString  $ctlString "; #I removed newline, put back if run together occurs - $brkRefDesc - would print if I knew what it meant.
					$enableFlowStr = 0;
					doView();
				}
				else{
					if ($brktyp eq 'M'){  
						print "\nOperations: $context Main"; #I removed newline, put back if run together occurs
						$enableFlowStr = 1;  #only for record main
						doView();
					}
					else {
						print "\nOperations: $context $brktyps";#I removed newline, put back if run together occurs
						$enableFlowStr = 0;
						doView();
					}
				}
			}
		}
	}
	sub doFlow{
		while (readin()){
			if (/^BRK/){
				unshift @saved, $_ ;#push on stack so we don't lose it 
				doBreak();
			}
			elsif (/^(DSP|DRPD)/) { # there was an '=' sign on the end . Worked in Unix, Not in NT
				if(/^DSP/){ $prevSeg = 'DSP';}
				unshift @saved, $_ ;
				last;
			}
		}
	}

	sub pickUpCommonDisplayFields {

	#	$col = '';	$row = '';	$rows = '';	$cols = '';	$color = '';  $attr = ''; $editType = '';
		$col = 0;	$row = 0;	$rows = '';	$cols = '';	$color = '';  $attr = ''; $editType = ''; #603

		$col   = $1 if /[{,]X=(\d+)/;
		$row   = $1 if /[{,]Y=(\d+)/;
		$cols  = $1 if /DX=(\d+)/;
		$rows  = $1 if /DY=(\d+)/;
		$color = $1 if /COLOR=(\d+)/;
		$attr  = expandIOmode('attr', $1) if /ATTR=(.),/;
		$editType  = expandIOmode('editControl', $1) if /TYPE=(.),/;
	}
	sub doDisplay_parseDitInfo{
		#default all the properties as we won't get the defaults.
		$clr = 0; $font = 0; $style = 0; $misc = 0; $align = 0; $para_align = 0; $dit_name = ''; $isn = 0; $static=0; $pb_action = 0; $pb_action_str = ''; #587
		$DIT_layer=0;$DIT_isnFather=0;#600

		$clr			= $1 if /CLR=(\d+)/;	#587  #NOTE That font, color, visibility, enable can all be expressions.
		$font			= $1 if /FONT=(\d+)/;	#587
		$style			= $1 if /STYLE=(\d+)/;	#587
		$misc			= $1 if /MISC=(\d+)/;	#587
		$align			= $1 if /ALIGN=(\d+)/;	#587
		$para_align		= $1 if /PARA_ALIGN=(\d+)/;	#587
		$dit_name		= $1 if /DIT_NAME="(.*?)"/;
		$isn			= $1 if /ISN=(\d+)/;	#587
		$static			= $1 if /STATIC=(\d+)/;	#587
		$pb_action		= $1 if /PB_ACT=(\d+)/; #587
		$pb_action_str  = $action_from_code{$pb_action};
		$DIT_layer      = $1 if /LAYER=(\d+)/;	#600
		$DIT_isnFather  = $1 if /ISN_FATHER=(\d+)/;	#600
		#print STDOUT " dbox $pic editType:$editType pb_act: $pb_action isn:$isn\n";
		#	print "DIT_INFO: dbox $pic editType:$editType pb_act: $pb_action isn:$isn\n";

		if    ($editType eq 'Static'){
			if    ($static == 1     ){ $editType = 'Rectangle';	}
			elsif ($static == 4     ){ $editType = 'Ellipse';	}
			elsif ($static == 8     ){ $editType = 'Line';	}
			elsif ($static == 128   ){ $editType = 'Group';	}
			else  { 				   $editType = 'Text';	}
		}
		elsif ($editType eq 'Slider'){
			if    ($style & 16384   ){ $editType = 'VertSlider'; }
			else                     { $editType = 'HorizSlider';	 }
		}
		elsif ($editType eq 'Radio'){
			if    ($style & 256     ){ $editType = 'Radio'; }
			elsif ($style & 512     ){ $editType = 'ComboBox'; }
			elsif ($style & 1024    ){ $editType = 'Tab'; }
			elsif ($style & 32768   ){ $editType = 'ListBox'; }
		}
		#600
		$frm_fnt = $font;
		makeFontString()      if defined($frm_fnt);

		if    ( $style & 0x01) { $ctl_style = '3DRaised';}
		elsif ( $style & 0x02) { $ctl_style = '3DSunken';}
		else                   { $ctl_style = '2D'       ;}

		if    ( $style & 0x04) { $ctl_border = 'ThinBorder';}
		elsif ( $style & 0x08) { $ctl_border = 'ThickBorder';}
		else                   { $ctl_border = 'NoBorder'   ;}

		$ctl_ScaledToFit = 0;	 			  
		if    ( $style &  0x0100000) { $ctl_ScaledToFit = 1 ;}
		$ctl_ScaledToFill = 0;	 			  
		if    ( $style &  0x0200000) { $ctl_ScaledToFill = 1 ;}
		$ctl_AllowCrInData = 0;	 			  
		if    ( $style & 0x04000000) { $ctl_AllowCrInData = 1 ;}

		$alignText ='';
		if ($align & 0x01   ){ $alignText .= "HLeft,";}
		if ($align & 0x02   ){ $alignText .= "HRight,";}
		if ($align & 0x04   ){ $alignText .= "HCenter,";}
		if ($align & 0x08   ){ $alignText .= "VTop,";}
		if ($align & 0x010  ){ $alignText .= "VCenter,";}
		if ($align & 0x020  ){ $alignText .= "VBottom,";}
		if ($align & 0x0100 ){ $alignText .= "Tabcontrolside:Top,";}
		if ($align & 0x0200 ){ $alignText .= "Tabcontrolside:Bottom,";}
		if ($align & 0x0400 ){ $alignText .= "Tabcontrolside:Left,";}
		if ($align & 0x0800 ){ $alignText .= "Tabcontrolside:Right,";}
		if ($para_align & 0x01 ){$alignText .= "PLeft,";}
		if ($para_align & 0x02 ){$alignText .= "PRight,";}
		if ($para_align & 0x04 ){$alignText .= "PCenter,";}

		#print "DIT_INFO: it=$it, itm_txt=$itm_txt, fldDesc=$fldDesc\n";#0611 Debug
		if ( $item !~ /Pushbutton/){
			if($fldDesc ne ''){
				$it = $fldDesc; $fldDesc ='';
			}
			elsif ( $exp ne '') {
				$it = $exp[$p][$t][$exp]; $exp = '' ;
			}
			else {
				$it = '';#A signal so the $itm_txt is moved in
			}
		}

		$otherCtlCharacteristics = '';
		$otherCtlCharacteristics .=	"FieldExp={"     . $exp[$p][$t][$exp]. '}' if (defined($exp) && $exp>0 && $item ne 'Field');
		$otherCtlCharacteristics .= " $ctl_style"   if defined $ctl_style;
		$otherCtlCharacteristics .= ", $ctl_border" if defined $ctl_border;

		$otherCtlCharacteristics .=	", $fontString" if defined($frm_fnt);
		$otherCtlCharacteristics .=	", FontExp={"    . $exp[$p][$t][$itmExp_fntExp] . '}'    if (defined($itmExp_fntExp) && $itmExp_fntExp>0);

		$otherCtlCharacteristics .=	", Color:$clr" if defined($clr);
		$otherCtlCharacteristics .=	", ColorExp={"   . $exp[$p][$t][$itmExp_clrExp]. '}' if (defined($itmExp_clrExp) && $itmExp_clrExp>0);
		$otherCtlCharacteristics .= ", ToolTipExp={" . $exp[$p][$t][$itmExp_tooltipExp]. '}' if(defined($itmExp_tooltipExp) && $itmExp_tooltipExp>0);
		$otherCtlCharacteristics .= ", EnableIf={"   . $exp[$p][$t][$itmExp_EnableExp ]. '}' if(defined($itmExp_EnableExp) && $itmExp_EnableExp>0);
		$otherCtlCharacteristics .= ", VisibleIf={"  . $exp[$p][$t][$itmExp_VisExp ]. '}' if(defined($itmExp_VisExp) && $itmExp_VisExp>0);
		$otherCtlCharacteristics .= ", RangeExp={"   . $exp[$p][$t][$itmExp_RngExp ]. '}' if(defined($itmExp_RngExp) && $itmExp_RngExp>0);

		$otherCtlCharacteristics .=	", $alignText";
		$otherCtlCharacteristics .=	", Tab=$isn" if (defined($isn) && $isn>0);
		$otherCtlCharacteristics .=	", Father=$DIT_isnFather" if (defined($DIT_isnFather) && $DIT_isnFather>0);
		$otherCtlCharacteristics .=	", Layer=$DIT_layer" if (defined($DiT_layer) && $DiT_layer>0) ;

		$otherCtlCharacteristics .=	", PDOD=$pdod_txt" if (defined($pdod_txt) && $pdod_txt!='');

		$otherCtlCharacteristics .=", ScaledToFit:$ctl_ScaledToFit"   if  $showScaledToFit;
		$otherCtlCharacteristics .=", ScaledToFill:$ctl_ScaledToFill" if  $showScaledToFill;
		$otherCtlCharacteristics .=", AllowCRInData:$AllowCrInData"   if  $showAllowCrInData;
	}
	sub	doDisplayPicOrExp{
		my $save;
		$save = $_;
		chomp($_);
		readin();
		if ( !/^EXP/){
			unshift @saved, $_ ;
		}
		else{
			$save .= $_; #concatenate the EXP line onto the end of PIC so it processes the same whether its 5.xx of 8.xx.
		}
		$_ = $save;

		$pic = '';
		$hlp = '';
		$exp = '';
		$exptxt = '';#600
		$prg = '';
		$mod = '';
		$allowInput = '';
		$mst = '';
		$ctrl = '';
		$ctrlstp  = '';
		$itmExp_clrExp =0;
		$itmExp_tooltip ='';
		$itmExp_fntExp =0;
		$itmExp_tooltipExp =0;
		$itmExp_EnableExp 	=0;
		$itmExp_VisExp 	=0;
		$itmExp_RngExp 	=0;

		$pic 		= $1 if /PIC="(.+?)"/;
		$hlp 		= $1 if /HLP=(.+?),/;
		$exp 		= $1 if /EXP=(\d+)/;
		$exptxt 	= $1 if /TXT=(.+?),/;#592
		$prg 		= $1 if /PRG=(.+?),/;
		$mod 		= $1 if /MOD=(.+?),/;
		$inp 		= $1 if /INP=(.+?),/;
		$mst 		= $1 if /MST=(.+?)\}/;
		$ctrl 		= $1 if /CTRL=(.+?),/;
		$ctrl_stp 	= $1 if /CTRL_STP="(.+?)"/;
		$pdod 		= $1 if /PDOD=(\d+)/;
		$itmExp_clrExp	= $1 if /CEXP=(\d+)/;
		$itmExp_tooltip = $1 if /TOOLTIP=(.)/;
		$itmExp_tooltipExp = $1 if /TOOLTIP_EXP=(\d+)/;
		$itmExp_fntExp 	= $1 if /FNT_EXP=(\d+)/;

		$itmExp_EnableExp 	= $1 if /INPNE_EXP=(\d+)/;
		$itmExp_VisExp 	= $1 if /VISIBLE=(\d+)/;
		$itmExp_RngExp 	= $1 if /RNG_EXP=(\d+)/;

		if (!defined($text )) {		$text  ='';	}
		if (!defined($exptxt)) {	$exptxt   ='';	}#600
		if (!defined($row  )) {		$row   ='';	}
		if (!defined($col  )) {		$col   ='';	}
		if (!defined($rows )) {		$rows  ='';	}
		if (!defined($cols )) {		$cols  ='';	}
		if (!defined($pic )) {		$pic  ='';	}
		if (!defined($attr )) {		$attr  ='';	}
		if (!defined($color)) {		$color ='';	}

		# Picture Detailed Options Data
		$pdod_txt='';
		if($pdod & 0x01 ){ $pdod_txt .='No Negative,';}
		if($pdod & 0x02 ){ $pdod_txt .= 'Commas,'; }
		if($pdod & 0x04 ){ $pdod_txt .= 'Zero fill,'; }
		if($pdod & 0x08 ){ $pdod_txt .= 'Left justify,'; }
		if($pdod & 0x10 ){ $pdod_txt .= 'Decimal point given,'; }
		if($pdod & 0x40 ){ $pdod_txt .= 'LongAlpha';}# 64 range is given for an alfa field and it is displayed longer than its original length'; }
		if($pdod & 0x80 ){ $pdod_txt .= 'Special';}#	128 Special negative or positive sign or suffix of a number or
		#										the length of a string it is displayed longer or shorter than its original length or
		#										there are some special character in the picture

		if ($item eq 'Field') {
		}
		elsif ( $item eq 'Expr' ) {
			$it = $exp[$p][$t][$exp];
		}
		else{
			print "missed item\n";
		}
		$~ = 'FORM_DETAIL_S' if (!$rowColumnFirst);
		$~ = 'NFORM_DETAIL_S' if( $rowColumnFirst);
		if (length($it) > 22 && !$rowColumnFirst){
			$~ = 'FORM_DETAIL_L';
		}
		if (length($it) > 35 && $rowColumnFirst){
			$~ = 'NFORM_DETAIL_L' if( $rowColumnFirst);
		}
		if ($magicVersion <= 599 ){
			write;
			undef($text );
			undef($itm_txt );
			undef($row );
			undef($col );
			undef($rows );
			undef($cols );
			undef($pic );
			undef($attr );
			undef($color );
		  }

	}
	sub	doDisplay{
		my $formNumber = 0;
		$prevSeg = 'DSP';
		print "\n// Display Items\n";
		print "// +-------- Name -------+Attr+-- Pic --+--------Pic-Exp--------+-Row+-Col+Rows+Cols+Allow+\n" if (!$rowColumnFirst);
		while (readin()){
			if (/^FRM/){#600:pick up form dimensions
				print "\nTableColumnWidths=$wcols" if defined $wcols;
				undef $frm_y,$frm_dx,$frm_dy;
				($frm_y,$frm_dx,$frm_dy ) = $_ =~ /FRM={Y=(\d+),DX=(\d+),DY=(\d+)/;
				print ", y=$frm_y" if( defined($frm_y));
				print ", dx=$frm_dx" if( defined($frm_dx));
				print ", dy=$frm_dy" if( defined($frm_dy));
				print "\n";
			}
			elsif (/^ROW_H/){
				chomp;
				print "$_"; #600. Want the newline
			}
			elsif (/^PROPLIST=\{MODEL=\"(.+)\"/) { #expect FIELD, FORM, CTRL
				doPropList();
			}
			elsif (/^BLOCK/){ #Form Detail header
				print $_; #600. Want the newline
				if ($frm_style eq 'HTMLMerge'){#0609
					print "TagName\tPicture\tReplaceWith\n";
				}
				else {
				print "+-Row-Col-Rows-Cols-Allow------- Name -------------------Attr-Pic---------------------------+\n" if ($rowColumnFirst);
				}
			}
			elsif (/^ACTV/){
				my $something;
			}
			elsif (/^MERGE_PARM/){#0609
				my $picExp;
				undef $picExp;
				undef $fld;
				undef $exp;
				undef $pic;
				$fld = $1 if $_ =~ /FLD="([A-Z]+)"/;
				$exp = $1 if $_ =~ /\{EXP=(\d+)/;
				$mergeString = varDesc($fld) if defined($fld);
				$mergeString = "Expr: " . $exp[$p][$t][$exp] if defined($exp);
				$picExp = $1 if /TEXP=(\d+)/;
				$pic = $exp[$p][$t][$picExp]; #Actually an expression defining the picture.
				readin() if !defined($picExp);  #if TEXP is defined, there will be no separate line for PIC and TXT.
				$pic = $1 if /PIC="(.+?)"/;
				$txt = $1 if /TXT="(.*?)"/;
				print "$txt\t$pic\t$mergeString\n";
			}
			elsif ( /^PROP={ID="TRIGGER/) {
				$trigContext = 'ITM';
			}
			elsif ( /^EVNT=/) {
				$trigContext = 'EVNT';
			}
			elsif (/^ITM=/){
				$prevSeg = 'ITM';
				printFormItem();#0611 - this prints out previous-
				#odd - i'd think the OLECLASS would push it out but it doesn't
				# not odd.  OLECLASS ends a static text item but for RTF and others its only mid item. 
				undef $fld;
				$attr = '';
				$pic = '';
				$fldDesc = '';
				$fld = $1 if /FLD="(.+?)"/;
				if ($magicVersion <= 599 ){
					pickUpCommonDisplayFields();
				}
				if (defined($fld)) {
					$it =  varDesc($fld);
					$fldDesc = $it;#600: initially for checkboxes
					$item = 'Field';
					#print "\n *** Field=$it **** \n";#0611 debug because I'm not seeing $it.
				}
				else {
					$item = 'Expr';
				}
			}
			elsif (/^DBOX=/) {	#version 600+
				pickUpCommonDisplayFields();
			}
			elsif (/^DIT_INFO=/) {	#version 600+
				doDisplay_parseDitInfo();
			}
			elsif (/^PLACE/){
				$printFormItem = 1;
				$itm_txt = $1 if /TXT="(.*)"\},/;
				$place_x = $1 if /[{,]X=(\d+)/;
				$place_y = $1 if /[{,]Y=(\d+)/;
				$place_dx = $1 if /DX=(\d+)/;
				$place_dy = $1 if /DY=(\d+)/;
				$otherCtlCharacteristics .= ',Place:' if ($place_x . $place_x  . $place_x . $place_x  . $place_x != '');
				$otherCtlCharacteristics .=  "X=$place_x," if $place_x;
				$otherCtlCharacteristics .=  "Y=$place_y," if $place_y;
				$otherCtlCharacteristics .=  "DX=$place_dx," if $place_dx;
				$otherCtlCharacteristics .=  "DY=$place_dy," if $place_dy		;
				if ( $item !~ /(CheckBox|Field|Expr)/) {
					$it = $itm_txt;
				}
			}
			#0611: in v5, TXT="..." will exist on its own line. There will never be an OLECLASS
			#0611: in v8, TXT="..." always exists after an OLECLASS.
			#0611: Therefore, I'm splitting this up for clarity.
			#0611: v8 only = only OLECLASS, sometimes a TXT=
			elsif (/^OLECLASS/) {	#0611: a TXT= may follow, if it doesn't, then its likely an RTF static.
				#print "OLECLASS: it=$it, itm_txt=$itm_txt, fldDesc=$fldDesc\n";#0611 Debug
				if( /TXT="(.+?)"}/ ){
					$itm_txt = $1;
				}
	#			if OLECLASS={}},
	#			else { #0613 look for the RTF tags. TXT_STRUCTURE, TXT
	#				readin(); #get next line
	#				if( /TXT_STRUCTURE=\{TXT_LEN="(.+?)"}/ ){
	#					$txt_len=$1;
	#				}
	#				else { # big problems. it should have matched.
	#					die "expected RTF TXT_STRUCTURE";
	#				}
	#				readin();
	#				if( /TXT="(.+?)"}/ ){
	#					$itm_txt = $1;
	#				}
	#				else { # big problems. it should have matched.
	#					die "expected RTF TXT";
	#				}
	#			}
				$~ = 'FORM_DETAIL_S' if (!$rowColumnFirst);
				$~ = 'NFORM_DETAIL_S' if( $rowColumnFirst);
				$printFormItem = 1;
				$item = $editType;
				if ( $item =~ /Text|Table|Rectangle|Ellipse|Line|Group|Text/ ){#600
					$attr = '';
				}
				if( $item =~ /Rectangle|Ellipse|Line|Group|Text/ ){
					$fldDesc = '';
				}
				if ( $item !~ /CheckBox|Field|Expr|Pushbutton/) { #!~  == doesn't match
					$it = $itm_txt;
				}
				if ( $item !~ /Pushbutton|Field/ && $it ne '') { #0611 added Field so that $it is not wiped out
					$it = $itm_txt;
				}
				if (length($it) > 22 && !$rowColumnFirst){
					$~ = 'FORM_DETAIL_L';
				}
				if (length($it) > 35 && $rowColumnFirst){
					$~ = 'NFORM_DETAIL_L' if( $rowColumnFirst);
				}
				if ($item !~ /(Text|Field|Expr|Table)/) {
					$~ = 'FORM_STATICS' if (!$rowColumnFirst);
					$~ = 'NFORM_STATICS' if( $rowColumnFirst);
					if (length($it) > 22 && $rowColumnFirst){
						$~ = 'NFORM_STATICS_L';
					}
				}
				if ($item eq 'CheckBox') {
					$~ = 'FORM_CheckBox' if (!$rowColumnFirst);
					$~ = 'NFORM_CheckBox' if( $rowColumnFirst);
				}
				if ($item eq 'Pushbutton') {
					$~ = 'FORM_Statics'     if (!$rowColumnFirst);
					$~ = 'NFORM_PUSHBUTTON' if( $rowColumnFirst);
				}
				#0611 - note no printFormItem() here.  Its the ITM= that pushes them out.
			}
			#0611: v5 only = no OLECLASS
			elsif (/TXT="(.+?)"}/ && $magicVersion <= 599 ) {	#was simply /^TXT=/ 
				$itm_txt = $1;
				$~ = 'FORM_DETAIL_S' if (!$rowColumnFirst);
				$~ = 'NFORM_DETAIL_S' if( $rowColumnFirst);
				$printFormItem = 1;
				$it = $itm_txt;
				pickUpCommonDisplayFields();
					$cols = length($it); #603. Static text never has a DX tag. Simply the length of the string.
				$rows = 1; #603.  Its static text, always one row.
				$item = 'text';
				if (length($it) > 22 && !$rowColumnFirst){
					$~ = 'FORM_DETAIL_L';
				}
				if (length($it) > 35 && $rowColumnFirst){
					$~ = 'NFORM_DETAIL_L' if( $rowColumnFirst);
				}
				printFormItem(); #603 In 5.xx these are standalone.
				undef($text );
				undef($itm_txt );
				undef($exp_txt );
				undef($row );
				undef($col );
				undef($rows );
				undef($cols );
				undef($pic );
				undef($attr );
				undef($color );
			}
			elsif (/^PIC=|^EXP=\{/){#EXP= will sometimes exist in absence of PIC.
				doDisplayPicOrExp();
			}
			elsif (($name, $class)= $_ =~ /^DSP(?:_INFO)?=\{.*NAME="(.*?)",(?:CLSS=(\d+))?/) {#600:let there random text between INFO= and NAME - there's another line like this one.
				$prevSeg = 'DSP';
				#0609  PRINTING THE FORMS HERE
				undef $wcols;#600
				$formNumber++;
				print "\nForm: $formNumber $name";#600
				print " Class $class" if defined($class);
				#600 all
				print " Class 0" if !defined($class);
				undef $frm_mod, $frm_clr, $frm_sty, $frm_fnt, $frm_chld; #600
				$frm_mod = $1 if $_ =~ /MOD=(.)/;
				$frm_clr = $1 if $_ =~ /COLOR=(\d+)/;
				$frm_sty = $1 if $_ =~ /STYLE=(\d+)/;
				$frm_fnt = $1 if $_ =~ /FONT=(\d+)/;
				$frm_chld = $1 if $_ =~ /ISCHLD=(.)/;

				if    ( $frm_sty & 0x04	     ) { $frm_style = 'Java';}
				elsif ( $frm_sty & 0x08	     ) { $frm_style = 'HTMLFrameSet';}
				elsif ( $frm_sty & 0x10	     ) { $frm_style = 'GUI';}
				elsif ( $frm_sty & 0x80	     ) { $frm_style = 'WebOnlineResponse';}
				elsif ( $frm_sty & 0x800     ) { $frm_style = 'HTMLMerge';}
				elsif ( $frm_sty & 0x2000000 ) { $frm_style = 'TextBased';}
				elsif ( $frm_sty & 0x40000000) { $frm_style = 'HTMLDocument';}
				elsif ( $frm_sty & 0x60000000) { $frm_style = 'HTML';}
				else                           { $frm_style = 'Online'   ;}

				if    ( $frm_sty & 0x20	     ) { $frm_style .= ',ThinBorder';}
				elsif ( $frm_sty & 0x40	     ) { $frm_style .= ',ThickBorder';}

				if    ( $frm_sty & 0x100     ) { $frm_style .= ',SystemMenu';}
				if    ( $frm_sty & 0x200     ) { $frm_style .= ',Minimize';}
				if    ( $frm_sty & 0x400     ) { $frm_style .= ',Maximize';}

				if    ($frm_mod eq 'H') { $frm_mod = 'Header' ;}
				elsif ($frm_mod eq 'F') { $frm_mod = 'Footer' ;}
				elsif ($frm_mod eq 'N') { $frm_mod = 'Detail' ;}
				elsif ($frm_mod eq 'P') { $frm_mod = 'PageHeader' ;}
				elsif ($frm_mod eq 'G') { $frm_mod = 'PageFooter' ;}
				else                    { $frm_mod = '??' ;}

				print " Type:$frm_style, $frm_mod";
				print ", IsChild:$frm_chld" if defined($frm_chld);
				print ", Color:$frm_clr" if defined($frm_clr);
				makeFontString()      if defined($frm_fnt);
				print ", $fontString" if defined($frm_fnt);

				#print "\n"; #600
			}
			elsif (/^UOM/){#600
				undef $frm_uom_x, $frm_uom_y, $ndiv;
				($frm_uom_x, $frm_uom_y )= $_ =~ /X=(\d+),Y=(\d+)/;
				($ndiv )= $_ =~ /NDIV=(\d+)/; 
				chomp($_);
				print ", $_";
			}
			elsif (/^WCOLS/){#600
				$wcols .= ',' if defined $wcols;
				($width) = $_ =~ /WIDTH=(\d+)/;
				$wcols .= $width;
			}
			elsif (/^(EXP=\"|TSK|DRPD)/ || ($_ eq "PRG=\{\n")){  # there was an '=' sign on the end . Worked in Unix, Not in NT
				printFormItem();
				unshift @saved, $_ ;
				last;
			}
		}
	}

	sub getPrgResources_event{ #pass=2     ^EVNT=
		$exp  = '';
		$scope='';
		$actv ='';
		$key  ='';
		$actvstr ='';#587
		$keystr  ='';#587
		$time ='';
		$mod ='' ;

		$actv  = $1 if /ACTV=(\d+)/;
		$key   = $1 if /KEY=(\d+)/;
		$time  = $1 if /TIME=(\d+)/;

		$scope = ($1 eq 'S')?'Subtask':'   Task' if /SCOPE=(.)/;
		$exp = $exp[$p][$t][$1] if /EXP=(\d+)/;

		$evnt[$evnt]->{key}= $key;
		$evnt[$evnt]->{actv}= $actv;
		$evnt[$evnt]->{keystr}= '';#587
		$evnt[$evnt]->{actvstr}= '';#587
		$evnt[$evnt]->{keystr}= $key_from_code{$key} if $key ne '';#587
		$evnt[$evnt]->{actvstr}= $action_from_code{$actv} if $actv ne '';#587
		$evnt[$evnt]->{'time'}= $time;
		$evnt[$evnt]->{'exp'}= $exp;

		$evnt[$evnt]->{scope} = $scope;

		readin();
		($mode, $task, $lock, $punct) = $_ =~ /MOD=(.),TSK=(\d+),LOCK=(.)(.)/;
		$evnt[$evnt]->{progTask}= ($mode eq 'T')?'   Task:':'Program:';

		$evnt[$evnt]->{progTaskNumber}= $task;
		$evnt[$evnt]->{lock}= $lock;
		if ($punct eq ',') {
			getArgsAndFlow();
			if (defined(@args))	{
				$i = 0;
				foreach $arg (@args){
					$evnt[$evnt]->{args}->[$i] = $arg;
					$i++;
				}
				undef(@args);
			}
		}
		$evnt++;
	}
	sub doPropList{
		$splitList = $1;
		undef @nodetype;
		@modeltype = split(/_/, $splitList );#eg FORM_GUI0, CTL_GUI0_EDIT
		$propList = $modeltype[0];#eg FORM, CTRL
		$propType = $modeltype[1];#eg GUI0
		$propObject = '';
		$propObject = $modeltype[2] if defined $modeltype[2]; #eg EDIT,STATIC
		$propObject .= '_' . $modeltype[3] if defined $modeltype[3];
#		print STDOUT "PROPLIST: $splitList; $propList, $propType, $propObject\n";
		setPropListType();
#			if( $lineNumber >125300){
#				print STDOUT "  --parseprog: PROPLIST: $lineNumber $propListType  \n\tTHIS:$_, \n\tPREV:$prevline";
#			}
	}
	sub	getPrgResources #pass=2
	{
		readin();
		die "expected RSRCE" if $_ !~ /^RSRCE/;

		while ( readin()) {
			if (/^DB/){
				$db++;
				($i) = $_ =~ /FILE=\{OBJ=(\d+)\}/;
				$db[$db]->{idx} 	= $i;
				$db[$db]->{file} 	= 'None Defined';
				$db[$db]->{file} 	= expandYNexp($1) if  $_ =~ /EXP=(\d+),/;
				$db[$db]->{access}  = expandIOmode('mod', $1) if $_ =~ /MOD=(.)/;
				$db[$db]->{share}  	= expandIOmode('opn', $1) if $_ =~ /OPN=(.)/;
				$db[$db]->{'open'}  	= expandIOmode('read', $1) if $_ =~ /READ=(.)/;
				$db[$db]->{cache}= $1 if $_ =~ /SIZ=([0-9YN]+)/;  #601  can be number, Y or N
			}
			elsif (/^IO/){
				$io++;
				$prgtaskName[$p]->{$hier}->{io}->[$io]->{desc}   = $1 if $_ =~ /DESC="(.*?)",/;
				$prgtaskName[$p]->{$hier}->{io}->[$io]->{'format'} = $1 if $_ =~ /FRM=(.)/;
				$prgtaskName[$p]->{$hier}->{io}->[$io]->{media}  = $1 if $_ =~ /STRG=(.)/;
				$prgtaskName[$p]->{$hier}->{io}->[$io]->{access} = $1 if $_ =~ /MOD=(.)/;
				$prgtaskName[$p]->{$hier}->{io}->[$io]->{file} = $exp[$p][$t][$1] if $_ =~ /EXP=(\d+),/;
				($comment) = $_ =~  /COMMENT="([^"]+)"/;#I don't do anything with this.
				$comment =~ s//\n/g;#replace backspaces with new lines
				$prgtaskName[$p]->{$hier}->{io}->[$io]->{comment}   = $comment;
			}
			elsif (/^EVNT=\{/) {
				$trigContext = 'EVNT';
				getPrgResources_event();
			}
			elsif (/^DTLS/) {
				getDetails();
			}
			elsif (/^FLW=/) {
				doFlow();  #main part
			}
			elsif (/^DSP=/ ) {
				$prevSeg = 'DSP';
				unshift @saved, $_ ;
				doDisplay();
			}
			elsif (/^FLD/) { #do nothing as it was all done in prescan
			}
			elsif (/^PROPLIST=\{MODEL=\"(.+)\"/) { #expect FIELD, FORM, CTRL
				doPropList();
			}
			elsif ( /^PROP={ID="TRIGGER/) {
				$trigContext = 'ITM';
			}
			elsif (/^TSK=/) {
				dumpEvents();
				initTaskMain();
				setHierarchicalPosition();
			}
			elsif (/^HDR=/) {  #these are Task Hdrs.  The prog header is above this.
				$queryMode  = $1 if /QRY=(.),/;
				$modifyMode = $1 if /MDFY=(.),/;
				$deleteMode = $1 if /DEL=(.),/;
				$isResident = $1 if /RSDNT=(.),/;
				($taskComment) = $_ =~  /COMMENT="([^"]+)"/;
			}
			elsif ($_ eq "PRG={\n" || /^DRPD/ ) { #dropdown menus
				dumpEvents();
				unshift @saved, $_ ;
				last;
			}
		}
	}
	sub expandYNexp{
		my $x = shift;

		if ($x =~ /^(Y|N)$/){
			$x = $x eq 'N'?'No':'Yes';
		}
		elsif ($x =~ /(\d+)/) {
			if (defined($exp[$p][$t][$1])) {
				$x = $exp[$p][$t][$1];
			}
		}
		$x;
	}
	sub ynexp{
		my ( $field, $str) = @_;
		my $result = '?undefined?';

		if ($str =~ /=\{$field=(Y|N)/){
			$result = $1;
		}
		elsif ($str =~ /EXP=(\d+)/) {
			$result = $exp[$p][$t][$1];
		}
		$result;
	}
	sub extendYN{
		my $x = shift;

		if ($x =~ /^(Y|N)$/){
			$x = $x eq 'N'?'No':'Yes';
		}
		elsif ($x eq 'A') {
			$x = 'Ascending';
		}
		elsif ($x eq 'D') {
			$x = 'Descending';
		}
		$x;
	}
	sub dumpEvents{
		my $i;

		return if (!defined($evt[$p]->{$hier}->{1}));
		print "\n// Events:\n\n";
		print "// ## Description            Trigger Type      Trigger      Force Exit     Public Name    Expose\n";
		print "//--------------------------------------------------------------------------------------------------------------------------------\n";
		$i = 1;
#		$xx =  defined($evt[$p]->{$hier});
#		print STDOUT "xx=$xx p=$p hier=$hier\n";
		while (defined ($evt[$p]->{$hier}->{$i})) {
			$index = "T$i";
			$event_desc = $evt[$p]->{$hier}->{$i}->{desc};
			$event_forceExit = $evt[$p]->{$hier}->{$i}->{forceexit};
			if ($event_forceExit eq 'N' ){$event_forceExit = 'None';}
			elsif ($event_forceExit eq 'C' ){$event_forceExit = 'Control';}
			elsif ($event_forceExit eq 'R' ){$event_forceExit = 'Record';}
			else {$event_forceExit = '?Other?';}
			
			#$event_forceExit = $evt[$p]->{$hier}->{$i}->{parent};
			#$event_forceExit = $evt[$p]->{$hier}->{$i}->{actv};
			#$event_forceExit = $evt[$p]->{$hier}->{$i}->{actvs};
			$trigtype = $evt[$p]->{$hier}->{$i}->{trigtype};
			$tts = $evt[$p]->{$hier}->{$i}->{tts};
			$trigger = $evt[$p]->{$hier}->{$i}->{trigger};
			
			$~ = 'EVENT_DETAIL';
			write;
			$i++;
		}
		print "\n";

	}
	sub dumpDBfiles{
		if (!defined($db[1])){
			return;
		}
		$v = 1;
		print "\n// DB Files:\n";
		print "//+Fil+---- File Name ---------+Access+Share+--Open--+-----Cache------+-Exp---+---Folder---+-------DB Name--------+---DB File------+\n"; #601 re-align
		while( defined($db[$v] )){
			$~ = 'DB_DETAIL';
			write;
			$v++;
		}
	}
	sub dumpSortSegs{
		if (!defined($sortSeg[1])){
			return;
		}
		$v = 1;
		print "\n Sort Segments:\n";
		print "  +-#--Direction-Size-Field--\n";
		while( defined($sortSeg[$v] )){
			$~ = 'SORT_DETAIL';
			write;
			$v++;
		}
		$nSortSegs = 0;
		undef @sortSeg;
	}
	sub dumpVirtuals {
		my $firstChar;

		if (!defined($virt[$p][$t][1])){
			return;
		}
		$v = 1;
		print "// Virtual Fields:\n";
		print "//#-+-- Name------ -----------------------Model--------------Attribute------- Picture -------Range--+\n";
		while( defined($virt[$p][$t][$v] )){
			$~ = 'VIRTUAL_DETAIL';
			write;

	#		printf( "% 4d %20s % 3d %7s %s\n",
	#				$v,
	#				$virt[$p][$t][$v]->{desc},
	#				$virt[$p][$t][$v]->{type},
	#				$virt[$p][$t][$v]->{attr},
	#				$virt[$p][$t][$v]->{pic}
	#			  );
			$v++;
		}
		#0606.01	dump again in tab separated format
		$v = 1;
		while (0) {
			print "//==Tab separated format for parameters:\n";
			print "//\tField Name\tTyp\tAttr\tPicture\tRange\tNotes\n"; #0607 knock off leading tab, add trailing tab and label for Notes
			while( defined($virt[$p][$t][$v]) ){
				$firstChar = substr( $virt[$p][$t][$v]->{desc},0,1);#0608 limit this dump to passed and returned values only
				if ( $firstChar eq 'p' ||  $firstChar eq 'r') { #0608
					printf( "%d\t%s\t%d\t%s\t%s\t\n", #0607 
							$v,
							$virt[$p][$t][$v]->{desc},
							$virt[$p][$t][$v]->{type},
							$virt[$p][$t][$v]->{attr},
							$virt[$p][$t][$v]->{pic}
						  );
				}
				$v++;
			}
		}
	}
	sub getSortSegs
	{
		$nSortSegs = 0;
		while (readin()) {
			if( /^SEG={FLD=(\d+),SIZ=(\d+),DIR=(.)/ ){
				$nSortSegs++;
				$sortSeg[ $nSortSegs ]->{'size'} = $2;
				$sortSeg[ $nSortSegs ]->{'direction'} = ($3 eq 'A')?'Ascending':'Descending';
				$sortSeg[ $nSortSegs ]->{'field'} = $var[$p]->{$hier}->{$1};
			}
			else {
				last;
			}
		}
		unshift @saved, $_;
	}
	sub	getDetails
	{
		$sqlCmd ='';
		$mainFile = 0;
		$mainKey = 0;
		$keyExpression = 0; #0585
		$keyInfo = "0.";  #0585
		while (readin()) {
			if (/^KEY/) {
				$mainKey = $1 if $_ =~ /FLD=(\d)/;#does not appear if no main file
				$mainMod = $1 if $_ =~ /MOD=(.)/; #0585 sample of expression for key: KEY={MOD=N,EXP=1},
				$keyExpression = $1 if $_ =~ /EXP=(\d+)/; #0585
			}
			elsif (/^DB/) {
				$mainFile = $1 if $_ =~ /DB=\{OBJ=(\d+)\}/;
				$mainFileDesc = $dd[$mainFile]->{desc};
			}
			elsif (/^SORT/) {
				getSortSegs();
			}
			elsif (/^FLW=(B|O),/) {
				($taskFlow,  $taskForceRecordDelete, $taskEndTaskCondition, $taskEndCheck ) = $_ =~ /FLW=(.),DEL=(\w+),END=(\w+),EMOD=(.),/;
				if ($taskForceRecordDelete =~ /\d+/) { $taskForceRecordDelete = $exp[$p][$t][$taskForceRecordDelete]; }
				if ($taskEndTaskCondition =~ /\d+/) { $taskEndTaskCondition = $exp[$p][$t][$taskEndTaskCondition]; }
				if ($taskFlow eq 'O' ) {
					$taskFlow = 'Online';
				}
				else {
					$taskFlow = 'Batch';
				}
			}
			elsif (/^MOD/) {
				$initialTaskMode = '?undefined?';
				if ($_ =~ /\{MOD=(.)/){
					$initialTaskMode = $initialTaskMode{$1};
				}
				elsif ($_ =~ /\{EXP=(\d+)/){
					$initialTaskMode = $exp[$p][$t][$1];
				}
			}
			elsif (/^LCT/) {
				$locateExp = 'None Defined';
				if ($_ =~ /\{EXP=(\d+)/){
					$locateExp = $exp[$p][$t][$1];
				}
				$locateDir = $1 if $_ =~ /DIR=(.)/;
				if    ($locateDir eq 'D' ) {$locateDir = 'Descending' ;}
				elsif ($locateDir eq 'A' ) {$locateDir = 'Ascending' ;}
			}
			elsif (/^RNG/) {
				($rangeComment) = $_ =~  /COMMENT="([^"]+)"/;#I don't do anything with this.
				$rangeExp = 'None Defined';
				if ($_ =~ /\{EXP=(\d+)/){
					$rangeExp = $exp[$p][$t][$1];
					#print STDOUT "Range Exp:$rangeExp\n";
				}
				$rangeDir = $1 if  $_ =~ /DIR=(.)/;
				if    ($rangeDir eq 'D' ) {$rangeDir = 'Descending' ;}
				elsif ($rangeDir eq 'A' ) {$rangeDir = 'Ascending' ;}
			}
			elsif (/^FLG/) {
				$selectionTask 	= expandYNexp( $1 ) if $_ =~ /SLCT=(.+?),/;
				$confirmUpdate	= expandYNexp( $1 ) if $_ =~ /CNF=(.+?),/;
				$sloc  			= $1 if $_ =~ /SLOC=(.)/;
				$sfail   		= $1 if $_ =~ /SFAIL=(.)/;
				$lstrg   		= $1 if $_ =~ /LSTRG=(.)/;
				$forceRecordSuffix   		= $1 if $_ =~ /SUFIX=(.)/;


				if    ($sloc eq 'R' ) {$sloc = 'Retry' ;}
				elsif ($sloc eq 'A' ) {$sloc = 'Abort' ;}
				elsif ($sloc eq 'S' ) {$sloc = 'Skip'  ;}

				if    ($sfail eq 'R' ) {$sfail = 'Retry' ;}
				elsif ($sfail eq 'A' ) {$sfail = 'Abort' ;}
				elsif ($sfail eq 'S' ) {$sfail = 'Skip'  ;}

				if    ($lstrg eq 'I' ) {$lstrg = 'Immediate'; }
				elsif ($lstrg eq 'O' ) {$lstrg = 'On_Modify' ;}
				elsif ($lstrg eq 'A' ) {$lstrg = 'After_Modify' ;}
				elsif ($lstrg eq 'B' ) {$lstrg = 'Before_Update' ;}
				elsif ($lstrg eq 'M' ) {$lstrg = 'Minimum' ;}

			}
			elsif (/^WIN/) {
				($openTaskWindow, $closeTaskWindow, $foregroundWindow, $flip) = $_ =~ /OPN=(.+?),CLS=(.+?),FGND=(.+?),FLIP=(.)/;
			}
			elsif (/^DTLS/) {
				$refreshWindow = $1 if $_ =~ /DTLS=\{RTRN=(.)/;
			}
			elsif (/^BOX/) {
			}
			elsif (/^UPD/) {
				($updateDate, $updateTime) = $_ =~ /UPD=\{DATE="(.+?)",TIME="(.+?)"/;
			}
			elsif (/^SQL_FORM/){#somewhat similar in processing to call prog/task
				#Basic format,  ^H are placeholders for newline.
				#RESTAB, INARG, OUTARG are optional. :N get replaced by inarg
				#SQL_FORM={DB="SQL_Database",RESTAB="Memory",SQL_STMT="select @@spid",
				#INARG={
				#ARG={EXP=1},
				#ARG={VAR="O"},
				#ARG={EXP=2},
				#ARG={VAR="P"},
				#ARG={EXP=3},
				#ARG={EXP=4}},
				#OUTARG={
				#ARG={VAR="CF"}}},
				#
				$sqlDbOut = '';
				$sqlDbIn = $1 if $_ =~ /DB="(.+?)",/;
				$sqlDbOut = $1 if  $_ =~ /RESTAB="(.+?)"/;
				$sqlCmd = $1 if  $_ =~ /SQL_STMT="(.+?)"/;
				($sqlComment) = $_ =~  /COMMENT="([^"]+)"/;
				getSQLArgs();
			}
			elsif (/^SIDE_WIN=\{/) {
				$allowOptions = 'Yes';
				$allowQuery = 'Yes';
				$allowModify = 'Yes';
				$allowCreate = 'Yes';
				$allowDelete = 'Yes';
				$allowLocate = 'Yes';
				$allowRange = 'Yes';
				$allowKeyChange = 'Yes';
				$allowSorting = 'Yes';
				$allowIOFiles = 'Yes';
				$allowCycleRecordMain = 'Yes';
				$allowReports = 'Yes';
				$allowAbort = 'Yes';
				$allowKeyOpt = 'Yes';
				$allowLocateInQuery = 'Yes';
				while (readin()) {
					if (/^WIN=\{/) {
						unshift @saved, $_ ;
						last;
					}
					else {
						$allowOptions = $1 if $_ =~ /SIDE_WIN=(N|Y)/;
						$allowQuery =   ynexp( "QRY", $_) if /^QRY/;
						$allowModify =  ynexp( "MDFY", $_ ) if /^MDFY/;
						$allowCreate =  ynexp( "CRT", $_ ) if /^CRT/;
						$allowDelete =  ynexp( "DEL", $_ ) if /^DEL/;
						$allowLocate =  ynexp( "LCT", $_ ) if /^LCT/;
						$allowRange =   ynexp( "RNG", $_ ) if /^RNG/;
						$allowKeyChange = ynexp( "KEY", $_ ) if /^KEY/;
						$allowSorting = ynexp( "SORT", $_ ) if /^SORT/;
						$allowIOFiles = ynexp( "FILE", $_ ) if /^FILE/;
						$allowCycleRecordMain = ynexp( "CYCL", $_ ) if /^CYCL/;
						$allowReports = ynexp( "RPR", $_ ) if /^RPR/;
						$allowAbort =   ynexp( "ABRT", $_ ) if /^ABRT/;
						$allowKeyOpt =  ynexp( "KOPT", $_ ) if /^KOPT/;
						$allowLocateInQuery = ynexp( "QLCT", $_ ) if /^QLCT/;
					}
				}
			}

			elsif (/^FLW=\{/) {
				$selectionTask        = extendYN( $selectionTask );
				$isResident 	      = extendYN($isResident);
				$openTaskWindow       = expandYNexp($openTaskWindow);
				$closeTaskWindow      = expandYNexp($closeTaskWindow);
				$foregroundWindow     = expandYNexp($foregroundWindow);
				$refreshWindow        = expandYNexp($refreshWindow);
				$flip                 = expandYNexp($flip);
				$allowCycleRecordMain = expandYNexp($allowCycleRecordMain);
				$confirmUpdate        = expandYNexp($confirmUpdate);
				$locateExp            = extendYN($locateExp);#already expanded to expression
				$rangeExp             = extendYN($rangeExp);#already expanded to expression
				$taskEndTaskCondition = extendYN($taskEndTaskCondition);#already expanded to expression
				$taskEndCheck = expandIOmode( 'endcheck', $taskEndCheck);
				$forceRecordSuffix = expandYNexp($forceRecordSuffix);#581
				$taskForceRecordDelete  = expandYNexp($taskForceRecordDelete);
				$allowOptions = extendYN($allowOptions);
				$allowModify = extendYN($allowModify);
				$allowCreate = extendYN($allowCreate);
				$allowDelete = extendYN($allowDelete);
				$allowQuery = extendYN($allowQuery);
				$allowLocate = extendYN($allowLocate);
				$allowRange = extendYN($allowRange);
				$allowKeyChange = extendYN($allowKeyChange);
				$allowSorting = extendYN($allowSorting);
				$allowIOFiles = extendYN($allowIOFiles);
				$allowAbort = extendYN($allowAbort);
				$allowKeyOpt = extendYN($allowKeyOpt);
				$allowLocateInQuery = extendYN($allowLocateInQuery);
				$allowReports = extendYN($allowReports);

				$taskName = ($hier eq '1')?$progName:$prgtaskName[$p]->{$hier}->{desc};
				 #0611c - add C subroutine end and start. Will cause us to have one extra unmatched close brace - who cares!
				print "}\n\001\nTask Name: $taskName (){ \t//Last Update: $updateDate $updateTime\n";#583

				if ($mainFile == 0 ) {
					$fileDesc = '';
					$keyDesc = '';
				}
				else {
					$fileDesc = $dd[$mainFile]->{desc};
					if ($mainKey == 0 ) {
						$keyDesc = '';
						if( $keyExpression ne 0 ){	#0585
							$keyInfo = "Expr: " . $exp[$p][$t][$keyExpression];	#0585
						}
					}
					else {
						$keyDesc = $dd[$mainFile]->{key}->[$mainKey];
						$keyInfo = "$mainKey. $keyDesc";  #0585
					}
				}
				print "-----\n";
				print "                Main File: $mainFile  $fileDesc   Key: $keyInfo\n";
				print "                Task Type: $taskFlow\n" if $taskFlow ne $ini{lc('deftaskFlow')};
				print "             Initial Mode: $initialTaskMode\n" if $initialTaskMode ne $ini{lc('defInitialTaskMode')};
				print "          Selection Table: $selectionTask\n" if $selectionTask ne $ini{lc('defselectionTask')};
				print "            Resident Task: $isResident\n" if $isResident ne $ini{lc('defisResident')};

				# //Task Control

				print "         Open Task Window: $openTaskWindow\n" if $openTaskWindow ne $ini{lc('defopenTaskWindow')};
				print "        Close Task Window: $closeTaskWindow\n" if $closeTaskWindow ne $ini{lc('defcloseTaskWindow')};
				print "        Foreground Window: $foregroundWindow\n" if $foregroundWindow ne $ini{lc('defforegroundWindow')};
				print "      Refresh Task Window: $refreshWindow\n" if $refreshWindow ne $ini{lc('defrefreshWindow')};

				print "      Flip Field on Input: $flip\n" if $flip ne $ini{lc('defflip')};
				print "        Cycle Record Main: $allowCycleRecordMain\n" if $allowCycleRecordMain ne $ini{lc('defallowCycleRecordMain')};
				print "           Confirm Update: $confirmUpdate\n" if $confirmUpdate ne $ini{lc('defconfirmUpdate')};
				print "             Form Records: 0\n" if $formRecords ne $ini{lc('def0')};

				print "               Locate Exp: $locateExp\n" if $locateExp ne $ini{lc('deflocateExp')};
				print "             Locate Order: $locateDir\n" if $locateDir ne $ini{lc('deflocateDir')};

				print "                Range Exp: $rangeExp\n" if $rangeExp ne $ini{lc('defrangeExp')};
				print "     Range/Locate Comment: $rangeComment\n" if $rangeComment ne "";
				print "              Range Order: $rangeDir\n" if $rangeDir ne $ini{lc('defrangeDir')};
				print "                 End Task: $taskEndTaskCondition\n" if $taskEndTaskCondition ne $ini{lc('deftaskEndTaskCondition')};
				print "                End Check: $taskEndCheck\n" if $taskEndCheck ne $ini{lc('deftaskEndCheck')};
				print "      Force Record Suffix: $forceRecordSuffix\n" if $forceRecordSuffix ne $ini{lc('defForceRecordSuffix')};
				print "      Force Record Delete: $taskForceRecordDelete\n" if $taskForceRecordDelete ne $ini{lc('deftaskForceRecordDelete')};

				print "         Locking Strategy: $lstrg\n" if $lstrg ne $ini{lc('deflstrg')};
				print "         On Locked Record: $sloc\n" if $sloc ne $ini{lc('defsloc')};
				print "  On Failed Record Access: $sfail\n" if $sfail ne $ini{lc('defsfail')};

				print "            Allow Options: $allowOptions\n"    if $allowOptions   ne $ini{lc('defallowOptions')}; #577
				print "             Allow Modify: $allowModify\n"     if $allowModify    ne $ini{lc('defAllowModify')};
				print "             Allow Create: $allowCreate\n"     if $allowCreate    ne $ini{lc('defAllowCreate')};
				print "             Allow Delete: $allowDelete\n" 	  if $allowDelete    ne $ini{lc('defAllowDelete')};
				print "              Allow Query: $allowQuery\n" 	  if $allowQuery     ne $ini{lc('defAllowQuery')};
				print "             Allow Locate: $allowLocate\n" 	  if $allowLocate    ne $ini{lc('defAllowLocate')};
				print "              Allow Range: $allowRange\n"      if $allowRange     ne $ini{lc('defAllowRange')};
				print "         Allow Key Change: $allowKeyChange\n"  if $allowKeyChange ne $ini{lc('defAllowKeyChange')};
				print "            Allow Sorting: $allowSorting\n"    if $allowSorting   ne $ini{lc('defAllowSorting')};
				print "          Allow I/O Files: $allowIOFiles\n"    if $allowIOFiles   ne $ini{lc('defAllowIOFiles')};
				print "              Allow Abort: $allowAbort\n"      if $allowAbort     ne $ini{lc('defAllowAbort')};
				print "   Allow Key Optimization: $allowKeyOpt\n"     if $allowKeyOpt    ne $ini{lc('defAllowKeyOpt')};
				print "    Allow Locate in Query: $allowLocateInQuery\n" if $allowLocateInQuery ne $ini{lc('defAllowLocateInQuery')};
				print "            Allow Reports: $allowReports\n" if $allowReports ne $ini{lc('defAllowReports')};


				if ($hier eq '1'){
					print "              Query Right: $queryRight\n" if $queryRight ne $ini{lc('defqueryRight')};
					print "             Modify Right: $modifyRight\n" if $modifyRight ne $ini{lc('defmodifyRight')};
					print "           Deletion Right: $deleteRight\n" if $deleteRight ne $ini{lc('defdeleteRight')};
					print "          Execution Right: $executeRight\n" if $executeRight ne $ini{lc('defexecuteRight')};

					
					printTaskHierarchy($p);
				}
				if($taskComment ne ''){
					$taskComment =~ s//\n/g;#replace backspaces with new lines
					print "-------------------------------\n";
					print "Comment: $taskComment\n";
					print "-------------------------------\n";
				}
				if( $sqlCmd ne '' ){
					print "----------------SQL Command ---------------------\n";
					if($sqlComment ne ''){
						$sqlComment =~ s//\n/g;#replace backspaces with new lines
						print $sqlComment;
					}
					print "DbIn: $sqlDbIn";
					print "\tDbOut: $sqlDbOut" if $sqlDbOut ne '';
					print "\n";
					$sqlCmd =~ s//\n/g;#replace backspaces with new lines
					print "SqlCmd: $sqlCmd\n";
					if (defined(@sqlArgs))	{
						#print "$flowstr";
						$i = 1;
						$j = $sqlArgInCnt;
						foreach $arg (@sqlArgs){
							$sqlArgType = 'Out';
							if( $j > 0 ){
								$sqlArgType = 'In';
							}
							$j--;
							print "\n";
							tabOut();
							printf( "\t% 3d|%s|%s", $i,$sqlArgType, $arg);
							if( $j == 0){$i=0;}
							$i++;
						}
						#$flowstr = '';
						undef(@sqlArgs);
					}
					print "\n-------------------------------------------------\n";
				}
				print "// Task Levels\n\n";


				dumpVirtuals();
				dumpDBfiles();
				dumpSortSegs();
				unshift @saved, $_;
				last;
			}
		}
	}
	sub	getSQLArgs {
		undef @sqlArgs;
		$sqlArgType='';
		$sqlArgInCnt=0;
		while (1){
			readin();
			if ( /^INARG/  ){$sqlArgType='In';}
			elsif ( /^OUTARG/  ){$sqlArgType='Out';}
			elsif ( /^ARG=\{EXP=(\d+)/  ){
				if ($sqlArgType eq 'In'){$sqlArgInCnt++;}
				my $tmp = $exp[$p][$t][$1];
				if ($tmp =~ /\'([A-Z]+)\'VAR/) {
					$tmp = '@' . varDesc($1);
				}
				push @sqlArgs, $tmp;
			}
			elsif (	/ARG=\{VAR="(\w+)"/  ){
				if ($sqlArgType eq 'In'){$sqlArgInCnt++;}
				push @sqlArgs, varDesc($1);
			}
#			elsif (	/ARG=\{SKIP=Y/  ){
#				push @sqlArgs, 'Parameter Skipped';
#			}
			else{
				unshift @saved, $_; # FLW should be next
				last;
			}
		}
	}
	sub initTaskMain{#pass=2
		$t++;
		$evnt = 0;
		undef @evnt;
		$io = 0;
		$db = 0;
		undef @db;
		$nSortSegs = 0;
		undef @sortSeg;
	}
	sub writeProgram #pass=2
	{
		$p++;
		$t=0;
		initTaskMain();
		$hier='1';
		$mainFile = 'None';

		readin();

		die "expected HDR" if $_ !~ /^HDR/;

		$progName = '--';  #There won't be a DESC token if there is no text #v055
		$progName = $1 if /DESC="(.+?)"/;
		$progPublic = '';
		$progPublic = $1 if /PUBLIC="(.+?)"/;
		$progFolder = $1 if /FOLDER="(.+?)"/;
		print STDOUT ".... $p. $progName [$progFolder]\n";
		$queryRight   = 'Not_Defined';
		$modifyRight  = 'Not_Defined';
		$deleteRight  = 'Not_Defined';
		$executeRight = 'Not_Defined';

		$queryRight   = rights($1) if /QRY=(\d+)/;
		$modifyRight  = rights($1) if /MDFY=(\d+)/;
		$deleteRight  = rights($1) if /DEL=(\d+)/;
		$executeRight = rights($1) if /EXE=(\d+)/;

		$isResident = $1 if /RSDNT=(.),/;
		($taskComment) = $_ =~  /COMMENT="([^"]+)"/;

		# replace characters prohibited in file names with hyphens so epsilon can write a file name
		# replace spaces so epsilon is not confused when creating buffer names
		$progAsFname = $progName;#600
		# I tried to retain spaces in filenames  but wasn't successful.
		# even if successful, wouldn't Epsilon get confused with buffer names?
		$progAsFname =~ tr/\\\/?*:<>% /-/;
	#   $progAsFname =~ tr/\\\/?*:<>%/-/; #0608 don't replace the spaces as I had been doing.
		$prgNumber = sprintf("%04d",$p);

		if( $ini{lc('generateHtml')} eq 'True' ){$FileExt = 'html'}#584
		else {$FileExt = 'txt'} #610 FileExt was ezr, but set to txt so Google will index it.
		$outfile = "z$prgNumber-$progAsFname." . $FileExt;

		print HTMLMAIN "<tr><td><a href=\"$outfile\"> $prgNumber </a><td><a href=\"$outfile\"> $progName </a>\n";#600

		open( OUT, "> $outfile" );
	#   open( OUT, "> \"$outfile\"" ); #0608 put quotes around the filename because it will have spaces - Doesn't work anyway
		select OUT;
		$startSecs = time;

		if ($os eq 'Windows_NT'){
	#		print "getting date and time\n";
			$date = `date /t`;
			$time = `time /t`;
	#		print "done getting date and time\n";
			chomp( $date );
			chomp( $time );
			$date .= ' ' . $time;
		}
		else{
			$date = 'n/a';
	#		$date = `date`;
		}
		if( $ini{lc('generateHtml')} eq 'True' ){ #584
			print "<html><title></title><body><pre>\n";
		}
		print "//mgFargo: Magic Source Translation - Version $mgMajorVers.$mgMinorVers $versionDate by Ira Gershenhorn w\\Perl $] \n";  #0614
		print "#define mgFargo 1\n\n";  #0614
		print " Program: $progName\t\tFolder:[$progFolder]\t\t$date";
		print "\t\tPublic:[$progPublic]" if $progPublic ne '';
		print "\n\n" ;

		$indentLevel = 1;
		$indentLevelPrev = 1;
		@indentExp =();
		getPrgResources(); #pass=2
		$elapsed = time - $startSecs;
		print "\n// Elapsed Time for $progName: $elapsed seconds\n\n";
		print STDOUT "\n// Elapsed Time for $progName: $elapsed seconds\n\n";
		undef $exp[$p];
		if( $ini{lc('generateHtml')} eq 'True' ){#584
			print "</pre></body></html>\n";
		}
		close OUT;
	}
	#getArgsAndFlow is a rearranger.  Magic outputs important info about a function on the
	# last line of the function, eg ARGS for raise event and all Calls.
	# This function moves that info up.
	# its safe to move everything after the }, as in ARG=(,SKIP=N|Y),
	#
	sub	pass2_rearrange_argfcn {#getArgsAndFlow {  #results either printed printProgArgs() or copied.
		$orig = $_;
		undef @lsaved; #lsaved is only used here, saved is used in readin.
		while (1){ #will fetch as many lines as needed.  Can't predict how many args there will be.
			readin();
			if (/^ARG=/){
				push @lsaved, $_;# save the arg line
				if (/FLW=\{/){ #concat the important peice of line to original.  Its important if has a FLW info. meaning its the last ARG
					if($_ =~ /},(.+$)/){ $piece = $1;}else {$piece='';}
					chomp($orig);
					$_ = $orig . 'HAS_ARG=Y,' . $piece ;
					last;
				}
			}
			else{ #didn't find an ARG -> time to leave loop, but shouldn't get here
				push @lsaved, $_;
				$_ = $orig;
				last; #don't process further, do the readin for next.
			}
		}
		unshift @saved, @lsaved; #add whole lsaved array to beginnnig of saved.eg if saved was ('C','D) and lsaved was ('A','B'), then after saved would be ('A','B','C','D)
		undef @lsaved;
	}
	sub printSubTree{
		my ($pp, $phier) = @_;

		$phier .= '.1';
		while ( defined(	$prgtaskName[$pp]->{$phier}->{desc})){
			$phierLessOne = substr($phier,1,10);
			$dots = $phier =~ tr/\./\./;#count em
			print  substr( $tabstr, 0, $dots+1), "$prgtaskName[$pp]->{$phier}->{desc}\t$phierLessOne\n";#600
			printSubTree($pp, $phier);
			$phier =~ s/(\d+)$/$1+1/e;  #Try the next one
		}
	}
	sub printTaskHierarchy {
		my $pp = shift;

		if (defined($prgtaskName[$pp]->{'1.1'}->{desc})){
			print "\nTask Hierarchy:";
			print "\n------------------------------------------------------------";#600
			print "\n\t$progName\n";

			printSubTree($pp, '1');
			print "------------------------------------------------------------\n";#600 
		}
	}


	sub usage{
	   pod2usage( { -message => "\n" . $0 . ": ". $error . "\n\n" . $copyrightLine ,
					-exitval => 1  ,  
					-input => $mgFargoIniPath . "mgFargo.pod",
					-verbose => 0  
					 } );
	}
	sub detailedUsage{
	   pod2usage( { -message => $copyrightLine ,
					-exitval => 0  ,  
					-verbose => 1,
					-input => $mgFargoIniPath . "mgFargo.pod",
					-output => \*STDOUT
					 } );
	}
	sub manpage{
	   pod2usage( { -message => $copyrightLine ,
					-exitval => 0  ,  
					-verbose => 2,
					-input => $mgFargoIniPath . "mgFargo.pod",
					-output => \*STDOUT
					 } );
	}
	sub read_mgFargo_ini{
		my $path = $1 if $file =~ /(^.*\/)/;
		my $ini = $path . 'mgFargo.ini';
		$ini = $mgFargoIniPath . 'mgFargo.ini';
		print STDOUT "testing for mgFargo.ini at [$ini]\n";
		if (!(-f $ini )){ print STDOUT "Warning: mgFargo.ini not found!\n";}
		else {
			my $skipping = 0;

			print STDOUT "opening $ini configuration parameters\n";
			open INI, "< $ini";
			while (<INI>) {

				if (!$skipping && /^(\w+)\s*=\s*([^\s;]+)/)	{
					$ini{lc($1)}=$2;
				}
				elsif ( /^\[(\w+)\]/){
					if ( $ini{lc('enableDefaults')} ne 'True' ){
						last;
					}
					elsif (	!/^\[$ini{lc('defaultsSection')}\]/i){
						$skipping = 1;
					}
				}
			}
			close INI;
		}

	}
	#Typical line
	# 0         1         2         3
	# 01234567890123456789012345678901234567890
	#User Action 1      =           ,  219,    0,0x000000000
	sub read_act_eng{ #587
		my $act_eng_path = $supportFilesPath;
		my $act_eng = $supportFilesPath . 'act_std.eng';
		print STDOUT "testing for act_std.eng at [$act_eng]\n";
		if (!(-f $act_eng )){ print STDOUT "Warning: act_std.eng not found!\n";}
		else {
			print STDOUT "opening $act_eng Actions Definition\n";
			open INI, "< $act_eng";
			while (<INI>) {
				$actcode = substr($_, 34,3);
				$actcode =~ s/ *([^ ]+)/$1/; #There's gotta be a cleaner way to strip leading space.
				$actstring = substr($_,0,18);

				$code_from_act{$actstring}= $actcode;
				$action_from_code{$actcode}=$actstring;

				$keycode = substr($_, 40,3);
				$keycode =~ s/ *([^ ]+)/$1/; #There's gotta be a cleaner way to strip leading space.
				$keystring = substr($_,21,10);

				$code_from_key{$keystring}= $keycode;
				$key_from_code{$keycode}=$keystring;
			}
			close INI;
		}
	}
	#600
	#Typical line
	# 0         1         2         3
	# 01234567890123456789012345678901234567890
	#Default Table Edit Field,MS Sans Serif,8,0,0
	sub read_fnt_eng{ #600
		my $fnt_eng_path = $supportFilesPath;
		my $fnt_eng = $fnt_eng_path . 'fnt_std.eng';
		my $fnt_index = 0;
		print STDOUT "testing for fnt_std.eng\n";
		if (!(-f $fnt_eng )){ print STDOUT "Warning: fnt_std.eng not found!\n";}
		else {
			print STDOUT "opening $fnt_eng Font Definition\n";
			open INI, "< $fnt_eng";
			while (<INI>) {
				chomp;
				$fnt_index+=1;
				($fnt_use, $fnt_face,$fnt_size,$fnt_number,$fnt_style) = split( /,/ );
				$fnt[$fnt_index]->{use} = $fnt_use;
				$fnt[$fnt_index]->{face} = $fnt_face;
				$fnt[$fnt_index]->{size} = $fnt_size;
				$fnt[$fnt_index]->{number} = $fnt_number;
				$fnt[$fnt_index]->{style} = $fnt_style;
			}
			close INI;
		}
	}

	sub makeFontString {
		$fontString = "Font:$frm_fnt,$fnt[$frm_fnt]->{use}~$fnt[$frm_fnt]->{face}~$fnt[$frm_fnt]->{size}~$fnt[$frm_fnt]->{style}";
	}
	sub printFormItem{
		if( $printFormItem){
			$printFormItem=0;
			write;
			undef($text );
			undef($itm_txt );
			undef($exp_txt );
			undef($row );
			undef($col );
			undef($rows );
			undef($cols );
			undef($attr );
			undef($color );
		}

	}

  sub basicUsage()
    {
        print STDERR << "EOF";

    This program does...

    usage: $0 [-isvh]

     -h        : this (help) message
     -v        : verbose output
     -i        : path to mgFargo.ini
     -s        : path to support files like act_std.eng

    example: $0 -i <path to mgFargo.ini> -s <path to Support files>  appExpFile

EOF
        exit;
    }

format SORT_DETAIL =
  @>>  @>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	$v, $sortSeg[$v]->{'direction'}, $sortSeg[$v]->{'size'}, $sortSeg[$v]->{'field'}
.

#no sequence numbers   #601 add DB tag and reduce indent
format DB_DETAIL =
DB @>> @<<<<<<<<<<<<<<<<<<<<<<< @<<<<< @<<<< @<<<<<<< @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<
   $db[$v]->{idx}, $dd[$db[$v]->{idx}]{desc}, $db[$v]->{access},$db[$v]->{share},$db[$v]->{'open'}, $db[$v]->{cache},$db[$v]->{file}, $dd[$db[$v]->{idx}]->{folder},$dd[$db[$v]->{idx}]->{dbname},$dd[$db[$v]->{idx}]->{name}
.

#format DB_DETAIL =
# @>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<  @<<<<<< @<<<<<<< @<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# $v, $db[$v]->{idx}, $dd[$db[$v]->{idx}]{desc}, $db[$v]->{access},$db[$v]->{share},$db[$v]->{'open'}, $db[$v]->{file}
#.

format VIRTUAL_DETAIL =
	   @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>> @<<<<<<<<<<<<< @<<<<<<<<<<<<<<< @<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
		$virt[$p][$t][$v]->{desc},	$virt[$p][$t][$v]->{model}, $virt[$p][$t][$v]->{model_desc},$virt[$p][$t][$v]->{attr}, $virt[$p][$t][$v]->{pic}, $virt[$p][$t][$v]->{range}, $virt[$p][$t][$v]->{comment}
.

# format VIRTUAL_DETAIL =
# @>>>> @<<<<<<<<<<<<<<<<<<<< @>>> @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# $v,	$virt[$p][$t][$v]->{desc},	$virt[$p][$t][$v]->{type}, $virt[$p][$t][$v]->{attr}, $virt[$p][$t][$v]->{pic}, $virt[$p][$t][$v]->{range}
#.

format HTML_HEADER =
<HTML>
   <HEAD>
	  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
	  <META NAME="Author" CONTENT="mgFargo">
	<TITLE>Application Directory</TITLE>
	</HEAD>
	<BODY>
	<H2>Application Program Files</h2>
	<TABLE WIDTH="100%" >
.

#New FORMAT formats which lead off with row colum.	     
format NFORM_DETAIL_L =
| @>> @>> @>> @>> @>> @>>>>>>>>>:                                    @>>>> @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $row, $col,$rows,$cols,$allowInput,$item,                  $attr,$pic,    $picExp,                $otherCtlCharacteristics
|                                @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
										$it
.

format NFORM_DETAIL_S =
// +-Row+-Col+Rows+Cols+Allow+-------- Name -------+Attr+-- Pic --+--------Pic-Exp--------\n";
| @>> @>> @>> @>> @>> @>>>>>>>>>:@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>> @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $row, $col,$rows,$cols,$allowInput,$item,   $it,         $attr,$pic,    $picExp,                $otherCtlCharacteristics
.

#600
format NFORM_STATICS =
| @>> @>> @>> @>>     @>>>>>>>>>:@<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<< @>>>> @<<<<<<<<<<<<<<<<<<<<< onReturn: @<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $row, $col,$rows,$cols,$item,   $it,                   $fldDesc,             $attr, $pic,                            $pb_action_str,      $otherCtlCharacteristics
.
#600
format NFORM_STATICS_L =
| @>> @>> @>> @>>     @>>>>>>>>>:                       @<<<<<<<<<<<<<<<<<<<<< @>>>> @<<<<<<<<<<<<<<<<<<<<< onReturn: @<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $row, $col,$rows,$cols,$item,                         $fldDesc,             $attr, $pic,                            $pb_action_str,      $otherCtlCharacteristics
|                                @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
								 $it
.
#600
format NFORM_PUSHBUTTON =
| @>> @>> @>> @>>     @>>>>>>>>>:@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>> @<<<<<<<<<<<<<<<<<<<<< onReturn: @<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $row, $col,$rows,$cols,$item,   $it,                                        $attr, $pic,                            $pb_action_str,      $otherCtlCharacteristics
.
#600
format NFORM_CheckBox =
| @>> @>> @>> @>> @>> @>>>>>>>>>:@<<<<<<<<<<<<<<<<< Label:@<<<<<<<<<<<<<<< onReturn: @<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $row, $col,$rows,$cols,$allowInput,$item,       $it,  $itm_txt,             $pb_action_str.      $otherCtlCharacteristics
.

#Original FORMAT formats
format FORM_DETAIL_L =
| @<<<<<:                        @<<<< @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<< @>>> @>>> @>>> @<<< @>>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $item,                       $attr,$pic,    $picExp,               $row, $col,$rows,$cols,$allowInput,$otherCtlCharacteristics
|      @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	  $it
.

format FORM_DETAIL_S =
//     +-------- Name -------+Attr+-- Pic --+--------Pic-Exp--------+-Row+-Col+Rows+Cols+Allow+\n";
| @<<<<<: @<<<<<<<<<<<<<<<<<<<<< @<<<< @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<< @>>> @>>> @>>> @<<<  @>>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 $item,   $it  ,              $attr,$pic,    $picExp,                $row,$col,$rows,$cols,$allowInput,$otherCtlCharacteristics
.

#587
format FORM_STATICS =
| @<<<<<<<<<: @<<<<<<<<<<<<<<<<<<<<< at:  @>>>, @>>> dimension: @>>>, @>>>> returnaction: @>>> @<<<<<<<<<<<<<<<<<<
 $item,      $pic,                  $row,$col,             $rows,$cols,$pb_action, $pb_action_str
.
#600
format FORM_CheckBox =
| @<<<<<<<<<: @<<<<<<<<<<<<<<<<< Label: @<<<<<<<<<<<<<<< at:  @>>>, @>>> dimension: @>>>, @>>>> returnaction: @>>> @<<<<<<<<<<<<<<<<<<
 $item,       $it,                      $itm_txt,             $row,$col,             $rows,$cols,$pb_action, $pb_action_str
.


#0573,#574
format EVENT_DETAIL =
@>>>> @<<<<<<<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<  @<<<<<<<<<<<<<<<<<<
$index, $event_desc,           $tts,          $trigger,               $event_forceExit, 
.
